<?php

//01-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent01Input.txt','r');
$currentFloor = 0;
while ($line = fgets($fh)) {
    $len = strlen($line);
    for($i=0;$i<$len;$i++){
        if(substr($line, $i, 1) == "(") $currentFloor += 1;
        else if(substr($line, $i, 1) == ")") $currentFloor -= 1;
    }
}
fclose($fh);
Log::write($currentFloor);*/


//01-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent01Input.txt','r');
$currentFloor = 0;
while ($line = fgets($fh)) {
    $len = strlen($line);
    for($i=0;$i<$len;$i++){
        if(substr($line, $i, 1) == "(") $currentFloor += 1;
        else if(substr($line, $i, 1) == ")") $currentFloor -= 1;
        if($currentFloor == -1){
            Log::write($i . " - " . $currentFloor);
        }
    }
}
fclose($fh);
*/



//02-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent02Input.txt','r');
$total = 0;
while ($line = fgets($fh)) {
    //Log::write($line);
    $items = explode("x", $line);
    $min = min($items[0]*$items[1], $items[0]*$items[2], $items[1]*$items[2]);
    $total += (2*$items[0]*$items[1]) + (2*$items[0]*$items[2]) + (2*$items[1]*$items[2]) + $min;
}
fclose($fh);
Log::write($total);
*/


//02-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent02Input.txt','r');
$total = 0;
while ($line = fgets($fh)) {
    //Log::write($line);
    $items = explode("x", $line);
    
    //Log::write($items);
    if(intval($items[0]) > intval($items[1])){
        $temp = $items[0];
        $items[0] = $items[1];
        $items[1] = $temp;
    }

    //Log::write($items);
    if(intval($items[1]) > intval($items[2])){
        $temp = $items[1];
        $items[1] = $items[2];
        $items[2] = $temp;
    }

    //Log::write($items);
    if(intval($items[0]) > intval($items[1])){
        $temp = $items[0];
        $items[0] = $items[1];
        $items[1] = $temp;
    }

    $temp = $items[0] + $items[0] + $items[1] + $items[1] + 
            ($items[0] * $items[1] * $items[2]);

    $total += $temp;
    //Log::write($items);
    //Log::write($line . " - " . $temp . " - " . ($items[0] + $items[0] + $items[1] + $items[1]) . " - " . $total);
}
fclose($fh);
Log::write($total);
*/




//03-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent03Input.txt','r');
$posX = 0;
$posY = 0;
$location = array();
$location[$posX . "-" . $posY] = 1;
while ($line = fgets($fh)) {
    //Log::write($line);

    $len = strlen($line);
    for($i=0;$i<$len;$i++){
        if(substr($line, $i, 1) == "^") $posY += 1;
        else if(substr($line, $i, 1) == "v") $posY -= 1;
        else if(substr($line, $i, 1) == "<") $posX -= 1;
        else if(substr($line, $i, 1) == ">") $posX += 1;

        $location[$posX . "-" . $posY] = 1;
    }

    //Log::write($location);
    Log::write(count($location));
}
fclose($fh);
*/



//03-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent03Input.txt','r');
$posX = 0;
$posY = 0;
$posRoboX = 0;
$posRoboY = 0;
$location = array();
$location[$posX . "-" . $posY] = 1;
while ($line = fgets($fh)) {
    //Log::write($line);

    $len = strlen($line);
    for($i=0;$i<$len;$i++){
        if($i % 2 == 0){
            if(substr($line, $i, 1) == "^") $posY += 1;
            else if(substr($line, $i, 1) == "v") $posY -= 1;
            else if(substr($line, $i, 1) == "<") $posX -= 1;
            else if(substr($line, $i, 1) == ">") $posX += 1;
    
            $location[$posX . "-" . $posY] = 1;
        } else {
            if(substr($line, $i, 1) == "^") $posRoboY += 1;
            else if(substr($line, $i, 1) == "v") $posRoboY -= 1;
            else if(substr($line, $i, 1) == "<") $posRoboX -= 1;
            else if(substr($line, $i, 1) == ">") $posRoboX += 1;
    
            $location[$posRoboX . "-" . $posRoboY] = 1;
        }
    }

    //Log::write($location);
    Log::write(count($location));
}
fclose($fh);
*/




//04-1
/*
$puzzleInput = "bgvyzdsv";
$found = false;
$idx = 0;
while(!$found){
    $str = $puzzleInput . "" . $idx;
    if(strcmp(substr(md5($str), 0, 5),"00000") == 0){
        Log::write($idx . " - " . md5($str) . " - " . substr(md5($str), 0, 5));
        $found = true;
    }
    $idx += 1;
}*/
//04-2
/*
$puzzleInput = "bgvyzdsv";
$found = false;
$idx = 0;
while(!$found){
    $str = $puzzleInput . "" . $idx;
    if(strcmp(substr(md5($str), 0, 6),"000000") == 0){
        Log::write($idx . " - " . md5($str) . " - " . substr(md5($str), 0, 6));
        $found = true;
    }
    $idx += 1;
}*/




//05-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent05Input.txt','r');
$countTotal = 0;
while ($line = fgets($fh)) {
    $condition1 = false;
    $condition2 = false;
    $condition3 = true;
    $len = strlen($line);

    $countVowel = 0;
    for($i=0;$i<$len;$i++){
        if(strcmp(substr($line, $i, 1),"a") == 0) $countVowel += 1;
        else if(strcmp(substr($line, $i, 1),"e") == 0) $countVowel += 1;
        else if(strcmp(substr($line, $i, 1),"i") == 0) $countVowel += 1;
        else if(strcmp(substr($line, $i, 1),"o") == 0) $countVowel += 1;
        else if(strcmp(substr($line, $i, 1),"u") == 0) $countVowel += 1;
    }

    if($countVowel >= 3){
        $condition1 = true;
    }

    
    for($i=1;$i<$len;$i++){
        if(strcmp(substr($line, $i-1, 1), substr($line, $i, 1)) == 0) 
            $condition2 = true;
    }

    for($i=1;$i<$len;$i++){
        if(strcmp(substr($line, $i-1, 1),"a") == 0 && strcmp(substr($line, $i, 1),"b") == 0) {
            $condition3 = false;
        } else if(strcmp(substr($line, $i-1, 1),"c") == 0 && strcmp(substr($line, $i, 1),"d") == 0) {
            $condition3 = false;
        } else if(strcmp(substr($line, $i-1, 1),"p") == 0 && strcmp(substr($line, $i, 1),"q") == 0) {
            $condition3 = false;
        } else if(strcmp(substr($line, $i-1, 1),"x") == 0 && strcmp(substr($line, $i, 1),"y") == 0) {
            $condition3 = false;
        }
    }


    if($condition1 && $condition2 && $condition3){
        $countTotal += 1;
    }
}
fclose($fh);
Log::write($countTotal);
*/

//05-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent05Input.txt','r');
$countTotal = 0;
while ($line = fgets($fh)) {
    $condition1 = false;
    $condition2 = false;
    $len = strlen($line);

    for($i=0;$i<$len-1;$i++){
        $strToCheck = substr($line, $i, 2);
        $idx = strpos($line, $strToCheck, $i+2);
        if($idx != false){
            $condition1 = true;
        }
    }

    for($i=2;$i<$len;$i++){
        if(strcmp(substr($line, $i-2, 1),substr($line, $i, 1)) == 0) {
            $condition2 = true;
        }
    }

    //Log::write($line . " - " . ($condition1 ? "true" : "false") . " - " . ($condition2 ? "true" : "false"));


    if($condition1 && $condition2){
        //Log::write($line . " nice");
        $countTotal += 1;
    } else {
        //Log::write($line);
    }
}
fclose($fh);
Log::write($countTotal);
*/




//06-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent06Input.txt','r');
$light = array();
for($i=0;$i<1000;$i++){
    $light[$i] = array();
    for($j=0;$j<1000;$j++){
        $light[$i][$j] = 0;
    }
}
while ($line = fgets($fh)) {
    $words = explode(" ", $line);
    //Log::write($words);
    if(count($words) == 4){
        
        $starts = explode(",",$words[1]);
        $ends = explode(",",$words[3]);
        $startX = intval($starts[0]);
        $endX = intval($ends[0]);
        $startY = intval($starts[1]);
        $endY = intval($ends[1]);

        for($x = $startX;$x <= $endX;$x++){
            for($y = $startY;$y <= $endY;$y++){
                $light[$x][$y] += 2;
            }
        }
    } else {
        $starts = explode(",",$words[2]);
        $ends = explode(",",$words[4]);
        $startX = intval($starts[0]);
        $endX = intval($ends[0]);
        $startY = intval($starts[1]);
        $endY = intval($ends[1]);

        if(strcmp($words[1],"on") == 0){
            for($x = $startX;$x <= $endX;$x++){
                for($y = $startY;$y <= $endY;$y++){
                    $light[$x][$y] += 1;
                }
            }
        } else {
            for($x = $startX;$x <= $endX;$x++){
                for($y = $startY;$y <= $endY;$y++){
                    $light[$x][$y] -= 1;
                    if($light[$x][$y] < 0) $light[$x][$y] = 0;
                }
            }
        }
    }
}
fclose($fh);
$total = 0;
for($i=0;$i<1000;$i++){
    for($j=0;$j<1000;$j++){
        $total += $light[$i][$j];
    }
}

Log::write($total);
*/




//07-1
/*
function decToBin16($val){
    return str_pad(decbin(intval($val)),16,"0",STR_PAD_LEFT);
}
function notOperator($str){
    $str = str_replace("0", "A", $str);
    $str = str_replace("1", "0", $str);
    $str = str_replace("A", "1", $str);
    return $str;
}
function andOrOperator($str1, $str2, $type){
    $strResult = "";
    for($i=0;$i<16;$i++){
        if($type == "AND"){
            $strResult .= (intval(substr($str1,$i,1)) == 1 && intval(substr($str2,$i,1)) == 1) ? "1" : "0";
        } else {
            $strResult .= (intval(substr($str1,$i,1)) == 1 || intval(substr($str2,$i,1)) == 1) ? "1" : "0";
        }
    }
    return $strResult;
}
class Bitwise{
    public $arr;
    public $wires;

	function __construct($arr) {
        $this->arr = $arr;
        $this->wires = array();
    }
    
    public function adventRecur($find){
        //Log::write($find);
        if(isset($this->wires[$find])) {
            return $this->wires[$find];
        }
        //Log::write($find . " - NOT FOUND");
        $found = false;
        for($i=0;$i<count($this->arr) && !$found;$i++){
            $len = count($this->arr[$i]);
            if(trim($this->arr[$i][$len-1]) == $find){
                $found = true;
                if($len == 3){
                    if(is_numeric($this->arr[$i][0])){
                        $this->wires[$find] = decToBin16($this->arr[$i][0]);
                    } else {
                        $this->wires[$find] = $this->adventRecur(trim($this->arr[$i][0]));
                    }
                } else if ($len == 4) {
                    $val = "";
                    if(isset($this->wires[trim($this->arr[$i][1])])) $val = $this->wires[trim($this->arr[$i][1])];
                    else $val = $this->adventRecur(trim($this->arr[$i][1]));

                    $this->wires[$find] = notOperator($val);
                } else if ($len == 5) {
                    $val1 = "";
                    if(isset($this->wires[trim($this->arr[$i][0])])) $val1 = $this->wires[trim($this->arr[$i][0])];
                    else if(is_numeric(trim($this->arr[$i][0]))) $val1 = decToBin16(trim($this->arr[$i][0]));
                    else $val1 = $this->adventRecur(trim($this->arr[$i][0]));
                    if (strcmp(trim($this->arr[$i][1]), "AND") == 0){
                        $val2 = "";
                        if(isset($this->wires[trim($this->arr[$i][2])])) $val2 = $this->wires[trim($this->arr[$i][2])];
                        else if(is_numeric(trim($this->arr[$i][2]))) $val1 = decToBin16(trim($this->arr[$i][2]));
                        else $val2 = $this->adventRecur(trim($this->arr[$i][2]));

                        $this->wires[$find] = andOrOperator($val1, $val2, "AND");
                    } else if (strcmp(trim($this->arr[$i][1]), "OR") == 0){
                        $val2 = "";
                        if(isset($this->wires[trim($this->arr[$i][2])])) $val2 = $this->wires[trim($this->arr[$i][2])];
                        else if(is_numeric(trim($this->arr[$i][2]))) $val1 = decToBin16(trim($this->arr[$i][2]));
                        else $val2 = $this->adventRecur(trim($this->arr[$i][2]));

                        $this->wires[$find] = andOrOperator($val1, $val2, "OR");
                    } else if (strcmp(trim($this->arr[$i][1]), "LSHIFT") == 0){
                        $this->wires[$find] = str_pad(substr($val1, intval(trim($this->arr[$i][2]))),16,"0",STR_PAD_RIGHT);
                    } else if (strcmp(trim($this->arr[$i][1]), "RSHIFT") == 0){
                        $this->wires[$find] = str_pad(substr($val1, 0, 16-intval(trim($this->arr[$i][2]))),16,"0",STR_PAD_LEFT);
                    }
                }
                return $this->wires[$find];
            }
        }
    }
}

$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent07Input.txt','r');
$arr = array();
$wires = array();
while ($line = fgets($fh)) {
    $arr[] = explode(" ", $line);
}

//Log::write($wires);
$bitWise = new Bitwise($arr);
Log::write( bindec($bitWise->adventRecur("a")));
// Log::write( bindec(adventRecur($arr, $wires, "e")));
// Log::write( bindec(adventRecur($arr, $wires, "f")));
// Log::write( bindec(adventRecur($arr, $wires, "g")));
// Log::write( bindec(adventRecur($arr, $wires, "h")));
// Log::write( bindec(adventRecur($arr, $wires, "i")));
fclose($fh);
*/






//08-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent08Input.txt','r');
$countString = 0;
$countMemory = 0;
while ($line = fgets($fh)) {
    $countMemory += strlen(trim($line));

    $substrIdx = 1;
    $tempStr = trim($line);
    while($substrIdx < strlen($tempStr) - 1){
        if(strcmp("\\x", substr($tempStr,$substrIdx,2)) == 0){
            $tempStr = substr($tempStr, 0, $substrIdx) . "-" . substr($tempStr, $substrIdx + 4);
        } else if(strcmp("\\\"", substr($tempStr,$substrIdx,2)) == 0){
            $tempStr = substr($tempStr, 0, $substrIdx) . "\"" . substr($tempStr, $substrIdx + 2);
        } else if(strcmp("\\\\", substr($tempStr,$substrIdx,2)) == 0){
            $tempStr = substr($tempStr, 0, $substrIdx) . "\\" . substr($tempStr, $substrIdx + 2);
            //$substrIdx += 1;
        }
        $substrIdx += 1;
    }
    Log::write(trim($line) . " - " . $tempStr);
    $countString += strlen($tempStr) - 2;
}
Log::write($countString . " - " . $countMemory);
Log::write($countMemory - $countString);
fclose($fh);*/

//08-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent08Input.txt','r');
$countString = 0;
$countMemory = 0;
while ($line = fgets($fh)) {
    $countString += strlen(trim($line));
    $len = strlen(trim($line));
    for($i=0;$i<$len;$i++){
        if(strcmp(substr(trim($line), $i, 1),"\\") == 0){
            $countMemory += 2;
        } else if(strcmp(substr(trim($line), $i, 1),"\"") == 0){
            $countMemory += 2;
        } else {
            $countMemory += 1;
        }
    }
    $countMemory += 2;
}
Log::write($countString . " - " . $countMemory);
Log::write($countMemory - $countString);
fclose($fh);*/





//09-1
/*
$lines = array();
$distance = array();
$nodes = array();
function calculate($distance, $nodes, $completedNodes){
    //Log::write($completedNodes);
    //$result = 99999; for 1st problem
    $result = 0;
    $lastNode = $completedNodes[count($completedNodes) - 1];
    $isNodeAvailable = false;
    foreach($nodes as $node){
        $found = false;
        foreach($completedNodes as $completedNode){
            if($completedNode == $node){
                $found = true;
            }
        }

        if(!$found){
            $tempCompletedNodes = $completedNodes;
            
            $tempCompletedNodes[] = $node;
            $tempResult = $distance[$lastNode][$node] + calculate($distance, $nodes, $tempCompletedNodes);
            // if($tempResult < $result){ for 1st problem
            //     $result = $tempResult;
            // }
            if($tempResult > $result){ 
                $result = $tempResult;
            }
            $isNodeAvailable = true;
        } 
    }
    if(!$isNodeAvailable) return 0;
    return $result;
}

$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent09Input.txt','r');
while ($line = fgets($fh)) {
    $lines[] = trim($line);
}

for($i=0;$i<count($lines);$i++){
    $items = explode(" ", $lines[$i]);
    if(!isset($nodes[$items[0]])){
        $nodes[$items[0]] = $items[0];
    }
    if(!isset($nodes[$items[2]])){
        $nodes[$items[2]] = $items[2];
    }
}
foreach($nodes as $node){
    $distance[$node] = array();
    foreach($nodes as $node2){
        $distance[$node][$node2] = 999999;
    }
}

for($i=0;$i<count($lines);$i++){
    $items = explode(" ", $lines[$i]);
    $distance[$items[0]][$items[2]] = intval($items[4]);
    $distance[$items[2]][$items[0]] = intval($items[4]);
}
//Log::write($nodes);
//Log::write($distance);


foreach($nodes as $node){
    $temp = array();
    $temp[] = $node;
    $result = calculate($distance, $nodes, $temp);
    Log::write($node . " - " . $result);
}

fclose($fh);
*/





//10-1
/*
$puzzleInput = "3113322113";
for($i=1;$i<=50;$i++){
    
    $len = strlen($puzzleInput);
    $prevChar = "X";
    $countChar = 0;
    $itResult = "";
    for($j=0;$j<$len;$j++){
        if(strcmp($prevChar, substr($puzzleInput,$j,1)) != 0){
            if($countChar > 0){
                $itResult .= $countChar . $prevChar;
            }
            $prevChar = substr($puzzleInput,$j,1);
            $countChar = 1;
        } else {
            $countChar += 1;
        }
    }
    
    $itResult .= $countChar . $prevChar;
    Log::write($i . " - " . strlen($itResult));
    $puzzleInput = $itResult;
}*/






//11-1
/*
function checkFirstReq($digits){
    $foundCorrect = false;
    for($i=2;$i<count($digits);$i++){
        if($digits[$i] - 1 == $digits[$i-1] && $digits[$i] - 2 == $digits[$i-2]){
            $foundCorrect = true;
        }
    }
    return $foundCorrect;
}
function checkSecondReq($digits){
    $foundWrong = false;
    for($i=0;$i<count($digits);$i++){
        if($digits[$i] == 8 || $digits[$i] == 11 || $digits[$i] == 14){
            $foundWrong = true;
        }
    }
    return !$foundWrong;
}
function checkThirdReq($digits){
    //Log::write("here");
    $idxFirstDouble = -1;
    $digitFirstDouble = -1;
    for($i=0;$i<count($digits)-1 && $idxFirstDouble == -1;$i++){
        if($digits[$i] == $digits[$i+1]){
            $idxFirstDouble = $i;
            $digitFirstDouble = $digits[$i];
        }
    }
    //Log::write($idxFirstDouble);
    //Log::write($digitFirstDouble);
    if($idxFirstDouble == -1) return false;
    //Log::write("found one");
    for($i=$idxFirstDouble+2;$i<count($digits)-1;$i++){
        if($digits[$i] == $digits[$i+1] && $digits[$i] != $digitFirstDouble){
            return true;
        }
    }
    return false;
}
function addOne($digits, $posDigit){
    $digits[$posDigit] += 1;
    if($digits[$posDigit] == 26){
        $digits[$posDigit] = 0;
        $digits = addOne($digits, $posDigit - 1);
    }
    if($digits[$posDigit] == 8 || $digits[$posDigit] == 11 || $digits[$posDigit] == 14){
        $digits[$posDigit] += 1;
        for($i=$posDigit+1;$i<count($digits);$i++){
            $digits[$i] = 0;
        }
    }
    return $digits;
}

//$puzzleInput = "hepxcrrq";
//$puzzleInput = "ghijklmn";
$puzzleInput = "hepxxyzz";
$digits = array();
for($i=0;$i<strlen($puzzleInput);$i++){
    $digits[] = ord(substr($puzzleInput, $i, 1)) - 97;
}
//Log::write($digits);

$digits = addOne($digits, 7);
Log::write($digits);
$found = checkFirstReq($digits) && checkSecondReq($digits) && checkThirdReq($digits);
// Log::write(checkFirstReq($digits) ? "1 true" : "1 false");
// Log::write(checkSecondReq($digits) ? "2 true" : "2 false");
// Log::write(checkThirdReq($digits) ? "3 true" : "3 false");

while(!$found){
    $digits = addOne($digits, 7);
    //Log::write($digits);
    $found = checkFirstReq($digits) && checkSecondReq($digits) && checkThirdReq($digits);
}
Log::write("finish");
Log::write($digits);
$res = "";
for($i=0;$i<count($digits);$i++){
    $res .= chr($digits[$i] + 97);
}
Log::write($res);
*/





//12-1
/*
function calculateNumber($items){
    //Log::write($items);
    $result = 0;
    foreach($items as $item){
        if(is_array($item)){
            $result += calculateNumber($item);
        } else if(is_object($item)){
            //Log::write($item);
            $foundRed = false;
            foreach($item as $it){
                if(strcmp(print_r($it, true), "red") == 0){
                    $foundRed = true;
                }
            }
            if(!$foundRed){
                //Log::write("no red");
                $result += calculateNumber($item);
            } else {
                //Log::write("red");
            }
        } else if(is_numeric($item)){
            $result += intval($item);
        } else {

        }
    }
    return $result;
}
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent12Input.txt','r');
$fullLines = "";
while ($line = fgets($fh)) {
    $fullLines .= trim($line);
}
$fullArray = json_decode($fullLines);
//Log::write($fullArray);
$result = calculateNumber($fullArray);
Log::write($result);
fclose($fh);
*/





//13-1
/*
function searchForNextNode($distance, $nodeList, $completedNodes){
    if(count($completedNodes) == count($nodeList)){
        return $distance[$completedNodes[0]][$completedNodes[count($completedNodes)-1]] + 
                $distance[$completedNodes[count($completedNodes)-1]][$completedNodes[0]];
    }
    $lastNode = $completedNodes[count($completedNodes) - 1];
    $result = -999999999;
    foreach($nodeList as $node){
        $foundDone = false;
        foreach($completedNodes as $completedNode){
            if($completedNode == $node){
                $foundDone = true;
            }
        }
        if(!$foundDone){
            $tempDone = $completedNodes;
            $tempDone[] = $node;
            $tempResult = $distance[$lastNode][$node] + $distance[$node][$lastNode] + searchForNextNode($distance, $nodeList, $tempDone);
            if($tempResult > $result){
                $result = $tempResult;
            }
        }
    }
    return $result;
}
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent13Input.txt','r');
$distance = array();
$nodeList = array();
while ($line = fgets($fh)) {
    $items = explode(" ", str_replace(".","",trim($line)));
    
    if(!isset($distance[$items[0]])){
        $distance[$items[0]] = array();
        $nodeList[] = $items[0];
    }

    $distance[$items[0]][$items[10]] = intval($items[3]) * (strcmp($items[2],"gain") == 0 ? 1 : -1);
}

//part two
$distance["ME"] = array();
for($i=0;$i<count($nodeList);$i++){
    $distance["ME"][$nodeList[$i]] = 0;
    $distance[$nodeList[$i]]["ME"] = 0;
}
$nodeList[] = "ME";

Log::write($distance);
foreach($nodeList as $node){
    //Log::write($node);
    $tempDone = array();
    $tempDone[] = $node;
    $result = searchForNextNode($distance, $nodeList, $tempDone);
    Log::write($node . " - " . $result);
}
fclose($fh);
*/






//14-1
/*
class Reindeer {
    public $name;
    public $status;
    public $distance;
    public $timeSinceChange;
    public $points;

    public $speed;
    public $flyTime;

    public $restingTime;

    function Reindeer($name, $speed, $flyTime, $restingTime){
        $this->name = $name;
        $this->status = 1;
        $this->distance = 0;
        $this->timeSinceChange = 0;
        $this->points = 0;

        $this->speed = $speed;
        $this->flyTime = $flyTime;

        $this->restingTime = $restingTime;
        
    }
}

$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent14Input.txt','r');
$reindeerList = array();
while ($line = fgets($fh)) {
    $items = explode(" ", trim($line));

    $reindeer = new Reindeer($items[0], intval($items[3]), intval($items[6]), intval($items[13]));
    $reindeerList[] = $reindeer;
}

//Log::write($reindeerList);

for($i=1;$i<=2503;$i++){
    $maxDistance = 0;
    foreach($reindeerList as $reindeer){
        $reindeer->timeSinceChange += 1;
        if($reindeer->status == 1){
            $reindeer->distance += $reindeer->speed;
            if($reindeer->timeSinceChange == $reindeer->flyTime){
                $reindeer->timeSinceChange = 0;
                $reindeer->status = 0;
            }
        } else {
            if($reindeer->timeSinceChange == $reindeer->restingTime){
                $reindeer->timeSinceChange = 0;
                $reindeer->status = 1;
            }
        }
        if($maxDistance < $reindeer->distance){
            $maxDistance = $reindeer->distance;
        }
    }

    
    foreach($reindeerList as $reindeer){
        if($reindeer->distance == $maxDistance){
            $reindeer->points += 1;
        }
    }
}
Log::write($reindeerList);
fclose($fh);
*/





//15-1
/*
$ingres = array();
$ingres[] = [5,-1,0,0,5];
$ingres[] = [-1,3,0,0,1];
$ingres[] = [0,-1,4,0,6];
$ingres[] = [-1,0,0,2,8];

$maxRes = 0;

for($i=0;$i<=100;$i++){
    for($j=0;$j<=100-$i;$j++){
        for($k=0;$k<=100-$i-$j;$k++){
            $remain = 100-$i-$j-$k;

            $capacity = max(0, $i*$ingres[0][0] + $j*$ingres[1][0] + $k*$ingres[2][0] + $remain*$ingres[3][0]);
            $durability = max(0, $i*$ingres[0][1] + $j*$ingres[1][1] + $k*$ingres[2][1] + $remain*$ingres[3][1]);
            $flavor = max(0, $i*$ingres[0][2] + $j*$ingres[1][2] + $k*$ingres[2][2] + $remain*$ingres[3][2]);
            $texture = max(0, $i*$ingres[0][3] + $j*$ingres[1][3] + $k*$ingres[2][3] + $remain*$ingres[3][3]);

            if($i*$ingres[0][4] + $j*$ingres[1][4] + $k*$ingres[2][4] + $remain*$ingres[3][4] == 500){ //for 15-2
                if($maxRes < $capacity * $durability * $flavor * $texture){
                    $maxRes = $capacity * $durability * $flavor * $texture;
                }
            }
        }
    }
}

Log::write($maxRes);
*/






//16-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent16Input.txt','r');

$targetSue = array();
$targetSue[] = "children: 3";
$targetSue[] = "cats: 7";
$targetSue[] = "samoyeds: 2";
$targetSue[] = "pomeranians: 3";
$targetSue[] = "akitas: 0";
$targetSue[] = "vizslas: 0";
$targetSue[] = "goldfish: 5";
$targetSue[] = "trees: 3";
$targetSue[] = "cars: 2";
$targetSue[] = "perfumes: 1";

$sues = array();
while ($line = fgets($fh)) {
    $byCommas = explode(", ", trim($line));

    $bySemi = explode(": ", $byCommas[0], 2);
    $items = array();
    $items[] = $bySemi[0];
    $items[] = $bySemi[1];
    $items[] = $byCommas[1];
    $items[] = $byCommas[2];

    $sues[] = $items;
}
$correctSue = -1;
for($i=0;$i<count($sues);$i++){
    $isWrongSue = false;
    for($j=1;$j<=3 && !$isWrongSue;$j++){
        $strToFind = $sues[$i][$j];
        $found = false;
        for($k=0;$k<count($targetSue);$k++){
            if(strcmp($strToFind, $targetSue[$k]) == 0){
                $found = true;
            }
        }
        if(!$found){
            $isWrongSue = true;
        }
    }

    if(!$isWrongSue){
        Log::write($sues[$i]);
    }
}
fclose($fh);
*/

//16-2
/*

$targetSue = array();
$targetSue['children'] = 3;
$targetSue['cats'] = 7;
$targetSue['samoyeds'] = 2;
$targetSue['pomeranians'] = 3;
$targetSue['akitas'] = 0;
$targetSue['vizslas'] = 0;
$targetSue['goldfish'] = 5;
$targetSue['trees'] = 3;
$targetSue['cars'] = 2;
$targetSue['perfumes'] = 1;

$sues = array();
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent16Input.txt','r');
while ($line = fgets($fh)) {
    $byCommas = explode(", ", trim($line));

    $bySemi = explode(": ", $byCommas[0], 2);
    $items = array();
    $items[] = $bySemi[0];
    $items[] = $bySemi[1];
    $items[] = $byCommas[1];
    $items[] = $byCommas[2];

    $sues[] = $items;
}
$correctSue = -1;
for($i=0;$i<count($sues);$i++){
    $isWrongSue = false;
    for($j=1;$j<=3 && !$isWrongSue;$j++){
        $strsToFind = explode(": ",$sues[$i][$j]);
        if(strcmp($strsToFind[0], "cats") == 0 || strcmp($strsToFind[0], "trees") == 0){
            if(intval($strsToFind[1]) <= $targetSue[$strsToFind[0]]){
                $isWrongSue = true;
            }
        } else if(strcmp($strsToFind[0], "pomeranians") == 0 || strcmp($strsToFind[0], "goldfish") == 0){
            if(intval($strsToFind[1]) >= $targetSue[$strsToFind[0]]){
                $isWrongSue = true;
            }
        } else {
            if(intval($strsToFind[1]) != $targetSue[$strsToFind[0]]){
                $isWrongSue = true;
            }
        }
    }

    if(!$isWrongSue){
        Log::write($sues[$i]);
    }
}
fclose($fh);
*/






//17-1
/*
function numOfVertex($cups, $remaining, $idx){
    // Log::write("remaining : " . $remaining . ", idx : " . $idx);
    if($remaining == 0) {
        // Log::write("final");
        return 0;
    }
    $result = count($cups) + 1;
    for($i=$idx;$i<count($cups);$i++){
        if($cups[$i] <= $remaining){
            // Log::write("cups : " . $cups[$i] . ", go : " . ($remaining - $cups[$i]));
            $tempResult = numOfVertex($cups, $remaining - $cups[$i], $i + 1) + 1;
            // Log::write("temp result : " . $tempResult);
            if($result > $tempResult){
                $result = $tempResult;
            }
        }
    }
    return $result;
}

function numOfPath($cups, $remaining, $idx, $maxVertex, $currentVertex){
    // Log::write("remaining : " . $remaining . ", idx : " . $idx);
    if($remaining == 0) {
        // Log::write("correct");
        if($currentVertex <= $maxVertex) return 1;
        return 0;
    }
    $result = 0;
    for($i=$idx;$i<count($cups);$i++){
        if($cups[$i] <= $remaining){
            $result += numOfPath($cups, $remaining - $cups[$i], $i + 1, $maxVertex, $currentVertex + 1);
        }
    }
    return $result;
}

$cups = array();
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent17Input.txt','r');
while ($line = fgets($fh)) {
    $cups[] = intval(trim($line));
}
fclose($fh);

rsort($cups);
// Log::write($cups);
$resultVertex = numOfVertex($cups, 150, 0);
Log::write($resultVertex);
$result = numOfPath($cups, 150, 0, $resultVertex, 0);
// $result = numOfPath($cups, 25, 0);
Log::write($result);
*/






//18-1
/*
function printMap($map, $maxSize){
    for($i=0;$i<$maxSize;$i++){
        $line = "";
        for($j=0;$j<$maxSize;$j++){
            $line .= $map[$i][$j] == 0 ? "." : "#";
        }
        Log::write($line);
    }
    Log::write("");
}
function checkMap($map, $maxSize, $i, $j){
    if(($i == 0 && $j == 0) || 
    ($i == 0 && $j == $maxSize - 1) || 
    ($i == $maxSize - 1 && $j == 0) || 
    ($i == $maxSize - 1 && $j == $maxSize - 1)) return 1;
    if($i < 0 || $i >= $maxSize || $j < 0 || $j >= $maxSize) return 0;
    return $map[$i][$j];
}
$map = array();
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent18Input.txt','r');
while ($line = fgets($fh)) {
    $mapLine = array();
    for($i=0;$i<strlen(trim($line));$i++){
        if(strcmp(".", substr(trim($line), $i, 1)) == 0){
            $mapLine[] = 0;
        } else {
            $mapLine[] = 1;
        }
    }
    $map[] = $mapLine;
}
fclose($fh);

$maxSize = count($map);
//printMap($map, $maxSize);
$iteNum = 100;
for($ite=0;$ite<$iteNum;$ite++){
    $newMap = array();
    for($i=0;$i<$maxSize;$i++){
        $newMapLine = array();
        for($j=0;$j<$maxSize;$j++){
            if(($i == 0 && $j == 0) || 
                ($i == 0 && $j == $maxSize - 1) || 
                ($i == $maxSize - 1 && $j == 0) || 
                ($i == $maxSize - 1 && $j == $maxSize - 1)){
                $newMapLine[] = 1;
            } else {
                $countOn = checkMap($map, $maxSize, $i-1, $j-1) +
                            checkMap($map, $maxSize, $i-1, $j) +
                            checkMap($map, $maxSize, $i-1, $j+1) +
                            checkMap($map, $maxSize, $i, $j-1) +
                            checkMap($map, $maxSize, $i, $j+1) +
                            checkMap($map, $maxSize, $i+1, $j-1) +
                            checkMap($map, $maxSize, $i+1, $j) +
                            checkMap($map, $maxSize, $i+1, $j+1);
                $countOff = 8 - $countOn;
                if($map[$i][$j] == 0){
                    $newMapLine[] = ($countOn == 3) ? 1 : 0;
                } else {
                    $newMapLine[] = ($countOn == 2 || $countOn == 3) ? 1 : 0;
                }
            }
        }
        $newMap[] = $newMapLine;
    }
    $map = $newMap;
}
printMap($map, $maxSize);
$count = 0;
for($i=0;$i<$maxSize;$i++){
    for($j=0;$j<$maxSize;$j++){
        $count += $map[$i][$j];
    }
}
Log::write($count);
*/






//19-1
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent19Input.txt','r');
$originalString = "";
$replacements = array();
while ($line = fgets($fh)) {
    $idx = strpos(trim($line), " => ");
    if($idx === false){
        if(strlen(trim($line)) > 1)
            $originalString = trim($line);
    } else {
        $replacements[] = explode(" => ", trim($line));
    }
}
Log::write($replacements);
Log::write($originalString);
fclose($fh);
$countDifferent = 0;
$listOfStr = array();
for($i=0;$i<count($replacements);$i++){
    $offset = 0;
    $idx = strpos($originalString, $replacements[$i][0], $offset);
    while($idx !== false){
        // Log::write($idx);
        $offset = $idx + 1;
        $newString = substr($originalString, 0, $idx) . $replacements[$i][1] . substr($originalString, $idx + strlen($replacements[$i][0]));

        //Log::write($newString . " - " . substr($originalString, 0, $idx) . " - " . $replacements[$i][1] . " - " . substr($originalString, $idx + strlen($replacements[$i][0])));
        $foundStr = false;
        for($j=0;$j<count($listOfStr) && !$foundStr;$j++){
            if(strcmp($newString, $listOfStr[$j]) == 0){
                $foundStr = true;
            }
        }
        if(!$foundStr){
            $listOfStr[] = $newString;
        }
        $idx = strpos($originalString, $replacements[$i][0], $offset);
    }
}
Log::write($listOfStr);
*/

//19-2
/*
$fh = fopen(PATH_CONTROLLERS . 'signin/advent/2015advent19Input.txt','r');
$destStr = "";
$replacements = array();
$token = array();
while ($line = fgets($fh)) {
    $idx = strpos(trim($line), " => ");
    if($idx === false){
        if(strlen(trim($line)) > 1)
            $destStr = trim($line);
    } else {
        $items = explode(" => ", trim($line));
        $replacements[] = $items;
        if(!isset($token[$items[0]])){
            $token[$items[0]] = $items[0];
        }
    }
}
Log::write($replacements);
Log::write($destStr);

$destStr = str_replace("Rn","(",$destStr);
$destStr = str_replace("Y",",",$destStr);
$destStr = str_replace("Ar",")",$destStr);
Log::write($destStr);
Log::write($token);
$i = 0;
$tokenCount = 0;
$countRnAr = 0;
$countY = 0;
while($i < strlen($destStr)){
    if(isset($token[substr($destStr,$i,1)])){
        $i++;
        $tokenCount += 1;
    } else if (isset($token[substr($destStr,$i,2)])){
        $i += 2;
        $tokenCount += 1;
    } else {
        if(strcmp(substr($destStr, $i, 1), "(") == 0 || strcmp(substr($destStr, $i, 1), ")") == 0){
            $countRnAr += 1;
        } else if (strcmp(substr($destStr, $i, 1), ",") == 0){
            $countY += 1;
        }
        $i++;
        $tokenCount += 1;
    }
}
Log::write($tokenCount);
Log::write($countRnAr);
Log::write($countY);
fclose($fh);
*/






//20-1
/*
$puzzleInput = 3600000;
$found = false;
$num = 500000;
while(!$found && $num < 700000){
    $temp = 0;
    for($i=1;$i<=intval(sqrt($num));$i++){
        if($num % $i == 0){
            if($num / $i == $i){
                $temp += $i;
            } else {
                $temp += ($num / $i) + $i;
            }
        }
    }
    if($temp >= $puzzleInput){
        Log::write("num : " . $num . ", present : " . $temp);
        Log::write("found");
        $found = true;
    }
    $num++;
}
Log::write("finished");*/

//20-2/*

/*
$puzzleInput = 36000000;
$num = 500000;
$presents = array();
for($i=1;$i<=($puzzleInput / 11) + 1;$i++){
    for($j=$i;$j<=$i*50 && $j <= ($puzzleInput / 11) + 1;$j += $i){
        if(!isset($presents[$j])) $presents[$j] = 0;
        $presents[$j] += $i;
    }
    // Log::write($presents);
}
$found = false;
for($i=1;$i<=($puzzleInput / 11) + 1 && !$found;$i++){
    if($presents[$i] > $puzzleInput / 11){
        $found = true;
        Log::write($i);
    }
}
Log::write("finished");*/








//21-1
class Fighter{
    public $damage;
    public $armor;
    public $hitPoints;
    public $cost;
    function __construct(){
        $this->damage = 0;
        $this->armor = 0;
        $this->hitPoints = 0;
        $this->cost = 0;
    }
}

class Item{
    public $cost;
    public $damage;
    public $armor;
    function __construct($cost, $damage, $armor){
        $this->cost = $cost;
        $this->damage = $damage;
        $this->armor = $armor;
    }
}

function createPlayer($weapon, $armor, $ringList){
    $player = new Fighter();
    $player->hitPoints = 100;

    $player->damage += $weapon->damage;
    $player->armor += $weapon->armor;
    $player->cost += $weapon->cost;

    if(!is_null($armor)){
        $player->damage += $armor->damage;
        $player->armor += $armor->armor;
        $player->cost += $armor->cost;
    }

    if(!is_null($ringList)){
        foreach($ringList as $ring){
            $player->damage += $ring->damage;
            $player->armor += $ring->armor;
            $player->cost += $ring->cost;
        }
    }

    return $player;
}

function willWin($boss, $player, $weapon, $armor, $ringList){
    while($player->hitPoints > 0){
        $boss->hitPoints -= max(1, $player->damage - $boss->armor);
        if($boss->hitPoints <= 0) {
            return true;
        }

        $player->hitPoints -= max(1, $boss->damage - $player->armor);
        // Log::write("condition");
        // Log::write("boss");
        // Log::write($boss);
        // Log::write("player");
        // Log::write($player);
    }
    Log::write($player);
    // Log::write($weapon);
    // Log::write($armor);
    // Log::write($ringList);
    return false;
}

$weaponList = array();
$weaponList[] = new Item(8, 4, 0);
$weaponList[] = new Item(10, 5, 0);
$weaponList[] = new Item(25, 6, 0);
$weaponList[] = new Item(40, 7, 0);
$weaponList[] = new Item(74, 8, 0);

$armorList = array();
$armorList[] = new Item(13, 0, 1);
$armorList[] = new Item(31, 0, 2);
$armorList[] = new Item(53, 0, 3);
$armorList[] = new Item(75, 0, 4);
$armorList[] = new Item(102, 0, 5);

$ringList = array();
$ringList[] = new Item(25, 1, 0);
$ringList[] = new Item(50, 2, 0);
$ringList[] = new Item(100, 3, 0);
$ringList[] = new Item(20, 0, 1);
$ringList[] = new Item(40, 0, 2);
$ringList[] = new Item(80, 0, 3);

$cost = 999999;
$costLose = 0;
for($i=0;$i<count($weaponList);$i++){
    //------------no armor
    //------------no ring
    // Log::write("no armor");
    // Log::write("no ring");
    $boss = new Fighter();
    $boss->damage = 8;
    $boss->armor = 2;
    $boss->hitPoints = 109;
    $player = createPlayer($weaponList[$i], null, null);
    if(willWin($boss, $player, $weaponList[$i], null, null)){
        if($cost > $player->cost){
            $cost = $player->cost;
        }
    } else {
        if($costLose < $player->cost){
            $costLose = $player->cost;
        }
    }
    
    //one ring
    //Log::write("one ring");
    for($j=0;$j<count($ringList);$j++){
        $boss = new Fighter();
        $boss->damage = 8;
        $boss->armor = 2;
        $boss->hitPoints = 109;
        $ringToWear = array();
        $ringToWear[] = $ringList[$j];
        $player = createPlayer($weaponList[$i], null, $ringToWear);
        if(willWin($boss, $player,$weaponList[$i], null, $ringToWear)){
            if($cost > $player->cost){
                $cost = $player->cost;
            }
        } else {
            if($costLose < $player->cost){
                $costLose = $player->cost;
            }
        }
    }
    //two ring
    //Log::write("two ring");
    for($j=0;$j<count($ringList)-1;$j++){
        for($k=$j+1;$k<count($ringList);$k++){
            $boss = new Fighter();
            $boss->damage = 8;
            $boss->armor = 2;
            $boss->hitPoints = 109;
            $ringToWear = array();
            $ringToWear[] = $ringList[$j];
            $ringToWear[] = $ringList[$k];
            $player = createPlayer($weaponList[$i], null, $ringToWear);
            if(willWin($boss, $player,$weaponList[$i], null, $ringToWear)){
                if($cost > $player->cost){
                    $cost = $player->cost;
                }
            } else {
                if($costLose < $player->cost){
                    $costLose = $player->cost;
                }
            }
        }
    }

    //one armor
    //Log::write("one armor");
    for($armorIndex=0;$armorIndex<count($armorList);$armorIndex++){
        //------------no ring
        //Log::write("no ring");
        $boss = new Fighter();
        $boss->damage = 8;
        $boss->armor = 2;
        $boss->hitPoints = 109;
        $player = createPlayer($weaponList[$i], $armorList[$armorIndex], null);
        if(willWin($boss, $player,$weaponList[$i], $armorList[$armorIndex], null)){
            if($cost > $player->cost){
                $cost = $player->cost;
            } else {
                if($costLose < $player->cost){
                    $costLose = $player->cost;
                }
            }
        }
        //one ring
        //Log::write("one ring");
        for($j=0;$j<count($ringList);$j++){
            $boss = new Fighter();
            $boss->damage = 8;
            $boss->armor = 2;
            $boss->hitPoints = 109;
            $ringToWear = array();
            $ringToWear[] = $ringList[$j];
            $player = createPlayer($weaponList[$i], $armorList[$armorIndex], $ringToWear);
            if(willWin($boss, $player,$weaponList[$i], $armorList[$armorIndex], $ringToWear)){
                if($cost > $player->cost){
                    $cost = $player->cost;
                }
            } else {
                if($costLose < $player->cost){
                    $costLose = $player->cost;
                }
            }
        }
        //two ring
        //Log::write("two ring");
        for($j=0;$j<count($ringList)-1;$j++){
            for($k=$j+1;$k<count($ringList);$k++){
                $boss = new Fighter();
                $boss->damage = 8;
                $boss->armor = 2;
                $boss->hitPoints = 109;
                $ringToWear = array();
                $ringToWear[] = $ringList[$j];
                $ringToWear[] = $ringList[$k];
                $player = createPlayer($weaponList[$i], $armorList[$armorIndex], $ringToWear);
                if(willWin($boss, $player,$weaponList[$i], $armorList[$armorIndex], $ringToWear)){
                    if($cost > $player->cost){
                        $cost = $player->cost;
                    }
                } else {
                    if($costLose < $player->cost){
                        $costLose = $player->cost;
                    }
                }
            }
        }
    }
}
Log::write($cost);
Log::write($costLose);

?>