Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- $filename = "18.txt";
- open(FILE, $filename);
- @data = <FILE>;
- close(FILE);
- @datacopy = @data;
- while ($#data > 0) { #Run code until only 1 line is remaining in input.
- $linea = $data[0]; #Take first and second line
- $lineb = $data[1];
- splice(@data, 1, 1);
- $linea =~ s/[^\[\]\,0-9]//sgi;
- $lineb =~ s/[^\[\]\,0-9]//sgi;
- $workset = "[".$linea.",".$lineb."]"; #Add together
- $outerchanged = 1;
- while ($outerchanged == 1) { #Run until no more changes at all can be made.
- $outerchanged = 0;
- $innerchanged = 1;
- while ($innerchanged == 1) { #Run until no more explosions can be made.
- $innerchanged = 0;
- $newworkset = preexplode($workset);
- if ($newworkset ne $workset) {
- $innerchanged = 1;
- $outerchanged = 1;
- }
- $workset = $newworkset;
- }
- $newworkset = dosplit($workset);
- if ($newworkset ne $workset) {
- $outerchanged = 1;
- }
- $workset = $newworkset;
- }
- $data[0] = $workset; #Replace first line with reduced set.
- }
- print $workset."\n";
- print premagnitude($data[0])."\n";
- $highestwk = 0;
- $cv = "";
- for ($i = 0; $i < $#datacopy + 1; $i++) {
- for ($n = $i + 1; $n < $#datacopy + 1; $n++) { #Try each line against each other in a bruteforce fashion
- $linea = $datacopy[$i];
- $lineb = $datacopy[$n];
- $linea =~ s/[^\[\]\,0-9]//sgi;
- $lineb =~ s/[^\[\]\,0-9]//sgi;
- $workset = "[".$linea.",".$lineb."]";
- $outerchanged = 1;
- while ($outerchanged == 1) {
- $outerchanged = 0;
- $innerchanged = 1;
- while ($innerchanged == 1) {
- $innerchanged = 0;
- $newworkset = preexplode($workset);
- if ($newworkset ne $workset) {
- $innerchanged = 1;
- $outerchanged = 1;
- }
- $workset = $newworkset;
- }
- $newworkset = dosplit($workset);
- if ($newworkset ne $workset) {
- $outerchanged = 1;
- }
- $workset = $newworkset;
- }
- $wkc = premagnitude($workset);
- if ($wkc > $highestwk) {
- $highestwk = $wkc;
- $cv = $workset;
- }
- }
- }
- print $cv."\n";
- print $highestwk."\n";
- sub dosplit() {
- my $zworkset = $_[0];
- my $num;
- my $lower;
- my $higher;
- if ($zworkset =~ m/(\d\d+)/) { #Any number with more than 1 digit
- $num = $1 / 2;
- $lower = int($num);
- $higher = int($num + 0.9);
- $zworkset =~ s/\d\d/\[$lower,$higher\]/; #Replace with the pair (split).
- }
- return $zworkset;
- }
- sub premagnitude() {
- my $zworkset = $_[0];
- my $pointer;
- my @chars = ('aa'..'zz','AA'..'ZZ');
- my $result;
- %recursive = ();
- for ($pointer = 0; $pointer < $#chars + 1; $pointer++) { #Put each pair in a hash array such as X = Y,Z, where Y/Z can be a real number or point at another hash array entry.
- $zworkset =~ s/\[([A-Za-z0-9]+),([A-Za-z0-9]+)\]/$chars[$pointer]/;
- $recursive{$chars[$pointer]} = $1.",".$2;
- if ($zworkset =~ m/^([A-Za-z0-9]+)$/) {
- last;
- }
- }
- $result = magnitude($zworkset);
- return $result;
- }
- sub magnitude() {
- my $input = $_[0];
- my $pa;
- my $pb;
- my $suma;
- my $sumb;
- ($pa, $pb) = split(",",$recursive{$input});
- if ($pa =~ m/^\d$/) { #If left part is a number, just put it in $suma.
- $suma = int($pa);
- }
- else
- {
- $suma = magnitude($pa); #If its a pair of letters, then we must dig deeper.
- }
- if ($pb =~ m/^\d$/) {
- $sumb = int($pb); #If right part is a number, just put it in $sumb
- }
- else
- {
- $sumb = magnitude($pb); #If its a pair or letters, then we must dig deeper.
- }
- return ($suma * 3) + ($sumb * 2);
- }
- sub preexplode() {
- my $zworkset = $_[0];
- my $pointer;
- my @chars = ('aa'..'zz','AA'..'ZZ');
- my $leftpart;
- my $rightpart;
- my $num;
- $leftnum = 0;
- $rightnum = 0;
- $didexplode = 0;
- %recursive = ();
- for ($pointer = 0; $pointer < $#chars + 1; $pointer++) { #Put each pair in a hash array such as X = Y,Z, where Y/Z can be a real number or point at another hash array entry.
- $zworkset =~ s/\[([A-Za-z0-9]+),([A-Za-z0-9]+)\]/$chars[$pointer]/;
- $recursive{$chars[$pointer]} = $1.",".$2;
- if ($zworkset =~ m/^([A-Za-z0-9]+)$/) {
- last;
- }
- }
- explode($zworkset, 0); #Run recursive function. This function MODIFIES %recursive directly (thats why I haven't prepended it with "my").
- while ($zworkset =~ m/[a-zA-Z]+/) {
- $zworkset =~ s/([a-zA-Z]+)/\[$recursive{$1}\]/g; #Reconstruct snailfish numbers from hash array by using regex to replace pair of letters with their corresponding pairs from hash array.
- }
- if ($zworkset =~ m/\[#\]/) { #There is a bomb, explode the bomb!
- ($leftpart, $rightpart) = split("#", $zworkset);
- if ($leftpart =~ m/([0-9]+)[^0-9]+[\[]$/) { #If there is any numbers to the left...
- $num = $1;
- $num = $num + $leftnum;
- $leftpart =~ s/([0-9]+)([^0-9]+)[\[]$/$num$2\[/; #Add it.
- }
- if ($rightpart =~ m/^[\]][^0-9]+([0-9]+)/) { #If there is any numbers to the right...
- $num = $1;
- $num = $num + $rightnum;
- $rightpart =~ s/^[\]]([^0-9]+)([0-9]+)/\]$1$num/; #Add it.
- }
- $zworkset = $leftpart."#".$rightpart; #Reconstruct the snailfish number with bomb.
- $zworkset =~ s/\[#\]/0/; #Replace bomb with 0 as its now exploded.
- }
- return $zworkset;
- }
- sub explode() {
- my $input = $_[0];
- my $count = $_[1];
- my $pa;
- my $pb;
- $count++;
- ($pa, $pb) = split(",",$recursive{$input});
- if (($count == 5)&&($didexplode == 0)) { #We have dig 5 steps deep, which is 4 steps from the beginning as we increase $count in beginning of function.
- $recursive{$input} = "#"; #Replace the pair with a bomb.
- $didexplode = 1; #Permanently disable any further exploding.
- $leftnum = $pa; #Save left num of pair.
- $rightnum = $pb; #Save right num of pair.
- }
- else
- {
- if ($pa =~ m/[a-zA-Z]+/) { #Any letters mean we need to dig deeper.
- explode($pa, $count);
- }
- if ($pb =~ m/[a-zA-Z]+/) { #Any letters mean we need to dig deeper.
- explode($pb, $count);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement