Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- use warnings;
- use strict;
- use Time::HiRes qw(time);
- my $disp_on = 0; # SET TO 0 TO DEACTIVATE DEBUG
- sub disp {
- if($disp_on == 1) {
- print $_[0]."\n";
- }
- }
- my $total = 0;
- my $starttime = time();
- my $filename = './input/day24.txt';
- open(FH, '<', $filename) or die $!;
- my @list;
- while(<FH>){
- chomp($_);
- push(@list,$_);
- }
- close(FH);
- my @selectionorder;
- my %group;
- my $teamnumber = 1;
- my $count = 0;
- foreach my $line (@list) {
- if($line eq "Infection:") { $teamnumber = 2; }
- if($line =~ /units/) {
- my @spl = split(/ /,$line);
- $group{$count}{"team"} = $teamnumber;
- $group{$count}{"number"} = $spl[0];
- $group{$count}{"hp"} = $spl[4];
- $group{$count}{"initiative"} = $spl[-1];
- my @spl2 = split(/that does /,$line);
- my @spl3 = split(/ damage/,$spl2[1]);
- my @spl4 = split(/ /,$spl3[0]);
- $group{$count}{"attackdmg"} = $spl4[0];
- $group{$count}{"attacktype"} = $spl4[1];
- $group{$count}{"weaknesses"} = "none";
- $group{$count}{"immuneto"} = "none";
- #disp $group{$count}{"attacktype"};
- if($line =~ /\(/) {
- @spl = split(/\(/,$line);
- @spl2 = split(/\)/,$spl[1]);
- my $weakimm = $spl2[0];
- my @wi = split(/; /,$weakimm);
- foreach my $el (@wi) {
- if($el =~ /weak/) { $group{$count}{"weaknesses"} = $el }
- if($el =~ /immune/) { $group{$count}{"immuneto"} = $el }
- }
- #disp $weakimm;
- }
- $count++;
- }
- }
- my $howmanygroups = $count;
- sub allInfo {
- for(my $i = 0; $i < $howmanygroups; $i++) {
- my $team = $group{$i}{"team"}; my $number = $group{$i}{"number"}; my $hp = $group{$i}{"hp"}; my $attackdmg = $group{$i}{"attackdmg"}; my $attacktype = $group{$i}{"attacktype"}; my $initiative = $group{$i}{"initiative"};
- print("ID ".$i." [Team ".$team."] Quantity: ".$number." | HP: ".$hp." | Dmg: ".$attackdmg." ".$attacktype." (total: ".($attackdmg*$number).") | Initiative: ".$initiative." | ".$group{$i}{"weaknesses"}." | ".$group{$i}{"immuneto"}."\n");
- }
- }
- print("Starting situation:\n");
- allInfo();
- sub defineSelectionOrder {
- @selectionorder = ();
- for(my $i = 0; $i < $howmanygroups; $i++) {
- if($group{$i}{"number"} > 0) {
- disp("- defineSelectionOrder - Pushing: ".$group{$i}{"number"}*$group{$i}{"attackdmg"}." ".$group{$i}{"initiative"}." ".$i);
- push(@selectionorder,([($group{$i}{"number"}*$group{$i}{"attackdmg"}),$group{$i}{"initiative"},$i]));
- }
- }
- @selectionorder = reverse sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @selectionorder;
- disp("- defineSelectionOrder - Order:");
- for(my $i = 0; $i <= $#selectionorder; $i++) { disp($i.": ".$selectionorder[$i][2]." (the group with ".$group{$selectionorder[$i][2]}{"number"}." units)") }
- disp("- defineSelectionOrder ---------");
- }
- sub attackDmg {
- my $attacker = $_[0];
- my $target = $_[1];
- disp("- attackDmg $attacker $target");
- my $strength = $group{$attacker}{"number"} * $group{$attacker}{"attackdmg"};
- disp("-- attackDmg Strength: $strength");
- my $atktype = $group{$attacker}{"attacktype"};
- disp("-- attackDmg Attack type: $atktype");
- if($group{$target}{"weaknesses"} =~ /$atktype/) { disp("-- attackDmg Target is weak!"); $strength = $strength * 2; }
- elsif($group{$target}{"immuneto"} =~ /$atktype/) { disp("-- attackDmg Target has immunity"); $strength = 0; }
- disp("-- attackDmg Final strength: $strength");
- return $strength;
- }
- sub selectTargets {
- for(my $tar = 0; $tar < $howmanygroups; $tar++) { $group{$tar}{"targetted"} = 0; $group{$tar}{"targetthisturn"} = -1; }
- for(my $s = 0; $s <= $#selectionorder; $s++) {
- my $i = $selectionorder[$s][2];
- my $team = $group{$i}{"team"};
- disp("- selectTargets with ".$i." (team ".$team.")");
- my $highestDmg = 0; my $highestIndex = -1;
- for(my $tar = 0; $tar < $howmanygroups; $tar++) {
- if($group{$tar}{"team"} != $team) {
- if($group{$tar}{"number"} > 0) {
- if($group{$tar}{"targetted"} == 0) {
- my $dmg = attackDmg($i,$tar);
- disp("-- selectTargets ".$tar." is a potential target. Dmg: ".$dmg);
- if($dmg > $highestDmg || $highestIndex == -1) { # If new best damage, no contest
- disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": new record");
- $highestDmg = $dmg;
- $highestIndex = $tar;
- } elsif($dmg == $highestDmg) { # First tie
- disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": tie!");
- if($group{$tar}{"number"} * $group{$tar}{"attackdmg"} > $group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"}) { # If new group has higher effective power, target this one
- disp("-- selectTargets Comparing old record's effective power ".($group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"})." to new ".($group{$tar}{"number"} * $group{$tar}{"attackdmg"}).": new record");
- $highestDmg = $dmg;
- $highestIndex = $tar;
- } elsif($group{$tar}{"number"} * $group{$tar}{"attackdmg"} == $group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"}) { # Second tie
- disp("-- selectTargets Comparing old record's effective power ".($group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"})." to new ".($group{$tar}{"number"} * $group{$tar}{"attackdmg"}).": tie!");
- if($group{$tar}{"initiative"} > $group{$highestIndex}{"initiative"}) { # If new group has higher initiative, target this one
- disp("-- selectTargets Comparing old record's initiative ".$group{$highestIndex}{"initiative"}." to new ".$group{$tar}{"initiative"}.": new record");
- $highestDmg = $dmg;
- $highestIndex = $tar;
- } else { disp("-- selectTargets Comparing old record's initiative ".$group{$highestIndex}{"initiative"}." to new ".$group{$tar}{"initiative"}.": not beaten"); }
- } else { disp("-- selectTargets Comparing old record's effective power ".($group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"})." to new ".($group{$tar}{"number"} * $group{$tar}{"attackdmg"}).": not beaten"); }
- } else { disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": not beaten"); }
- } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": already a target"); }
- } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": no more troops"); }
- } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": same team!"); }
- }
- disp("- selectTargets ".$i." has selected ".$highestIndex);
- $group{$i}{"targetthisturn"} = $highestIndex;
- $group{$highestIndex}{"targetted"} = 1;
- }
- }
- my @attackorder;
- sub defineAttackOrder {
- @attackorder = ();
- #disp("----- Attack order:");
- for(my $i = $howmanygroups; $i >= 0; $i--) {
- for(my $j = 0; $j < $howmanygroups; $j++) {
- if($group{$j}{"initiative"} == $i) {
- if($group{$j}{"number"} > 0) { push(@attackorder,$j); }
- last;
- }
- }
- }
- #disp("--------------------");
- }
- sub didSomeoneWin {
- my @teams; $teams[1] = 0; $teams[2] = 0;
- for(my $i = 0; $i < $howmanygroups; $i++) {
- if($group{$i}{"number"} > 0) {
- $teams[$group{$i}{"team"}]++;
- }
- }
- if($teams[1] == 0) { return 2 }
- elsif($teams[2] == 0 ) { return 1 }
- else { return 0; }
- }
- my $round = 1;
- while(didSomeoneWin() == 0) { # Main loop
- disp("!!! Round ".$round." !!!\n");
- defineSelectionOrder();
- selectTargets();
- defineAttackOrder();
- for(my $i = 0; $i <= $#attackorder; $i++) {
- my $attacker = $attackorder[$i];
- disp("Main loop: ".$attacker." will attack");
- if($group{$attacker}{"number"} > 0 && $group{$attacker}{"targetthisturn"} > -1) {
- my $defender = $group{$attacker}{"targetthisturn"};
- my $dmg = attackDmg($attacker,$defender);
- disp("Main loop: ".$attacker." will attack ".$defender." for ".$dmg);
- if($dmg >= $group{$defender}{"hp"} * $group{$defender}{"number"} ) {
- disp("Main loop: after ".$attacker."'s attack, defender ".$defender." has no more troops");
- $group{$defender}{"number"} = 0;
- }
- else {
- my $dead = int($dmg / $group{$defender}{"hp"});
- $group{$defender}{"number"} = $group{$defender}{"number"} - $dead;
- disp("Main loop: after ".$attacker."'s attack, defender ".$defender." loses ".$dead." troops. Remaining: ".$group{$defender}{"number"});
- }
- } else { disp("Main loop: ".$attacker." could not attack"); }
- }
- $round++;
- }
- print("Situation at the end:\n");
- allInfo();
- for(my $i = 0; $i < $howmanygroups; $i++) {
- $total += $group{$i}{"number"};
- }
- print("Total: ".$total);
- printf("[Ran in %0.1f milliseconds]\n", (time() - $starttime) * 1000);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement