Advertisement
Guest User

Untitled

a guest
Oct 30th, 2024
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Perl 8.46 KB | None | 0 0
  1. #!/usr/bin/perl
  2. use warnings;
  3. use strict;
  4. use Time::HiRes qw(time);
  5.  
  6. my $disp_on = 0; # SET TO 0 TO DEACTIVATE DEBUG
  7.  
  8. sub disp {
  9.     if($disp_on == 1) {
  10.         print $_[0]."\n";
  11.     }
  12. }
  13.  
  14. my $total = 0;
  15.  
  16. my $starttime = time();
  17.  
  18. my $filename = './input/day24.txt';
  19. open(FH, '<', $filename) or die $!;
  20. my @list;
  21. while(<FH>){
  22.     chomp($_);
  23.     push(@list,$_);
  24. }
  25. close(FH);
  26.  
  27. my @selectionorder;
  28.  
  29. my %group;
  30. my $teamnumber = 1;
  31. my $count = 0;
  32. foreach my $line (@list) {
  33.     if($line eq "Infection:") { $teamnumber = 2; }
  34.     if($line =~ /units/) {
  35.         my @spl = split(/ /,$line);
  36.         $group{$count}{"team"} = $teamnumber;
  37.         $group{$count}{"number"} = $spl[0];
  38.         $group{$count}{"hp"} = $spl[4];
  39.         $group{$count}{"initiative"} = $spl[-1];
  40.         my @spl2 = split(/that does /,$line);
  41.         my @spl3 = split(/ damage/,$spl2[1]);
  42.         my @spl4 = split(/ /,$spl3[0]);
  43.         $group{$count}{"attackdmg"} = $spl4[0];
  44.         $group{$count}{"attacktype"} = $spl4[1];
  45.         $group{$count}{"weaknesses"} = "none";
  46.         $group{$count}{"immuneto"} = "none";
  47.         #disp $group{$count}{"attacktype"};
  48.         if($line =~ /\(/) {
  49.             @spl = split(/\(/,$line);
  50.             @spl2 = split(/\)/,$spl[1]);
  51.             my $weakimm = $spl2[0];
  52.             my @wi = split(/; /,$weakimm);
  53.             foreach my $el (@wi) {
  54.                 if($el =~ /weak/) { $group{$count}{"weaknesses"} = $el }
  55.                 if($el =~ /immune/) { $group{$count}{"immuneto"} = $el }
  56.             }
  57.             #disp $weakimm;
  58.         }
  59.         $count++;
  60.     }
  61. }
  62. my $howmanygroups = $count;
  63.  
  64. sub allInfo {
  65.     for(my $i = 0; $i < $howmanygroups; $i++) {
  66.         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"};
  67.         print("ID ".$i." [Team ".$team."] Quantity: ".$number." | HP: ".$hp." | Dmg: ".$attackdmg." ".$attacktype." (total: ".($attackdmg*$number).") | Initiative: ".$initiative." | ".$group{$i}{"weaknesses"}." | ".$group{$i}{"immuneto"}."\n");
  68.     }
  69. }
  70.  
  71. print("Starting situation:\n");
  72. allInfo();
  73.  
  74. sub defineSelectionOrder {
  75.     @selectionorder = ();
  76.     for(my $i = 0; $i < $howmanygroups; $i++) {
  77.         if($group{$i}{"number"} > 0) {
  78.             disp("- defineSelectionOrder - Pushing: ".$group{$i}{"number"}*$group{$i}{"attackdmg"}." ".$group{$i}{"initiative"}." ".$i);
  79.             push(@selectionorder,([($group{$i}{"number"}*$group{$i}{"attackdmg"}),$group{$i}{"initiative"},$i]));
  80.         }
  81.     }
  82.     @selectionorder = reverse sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] } @selectionorder;
  83.     disp("- defineSelectionOrder - Order:");
  84.     for(my $i = 0; $i <= $#selectionorder; $i++) { disp($i.": ".$selectionorder[$i][2]." (the group with ".$group{$selectionorder[$i][2]}{"number"}." units)") }
  85.     disp("- defineSelectionOrder ---------");
  86. }
  87.  
  88. sub attackDmg {
  89.     my $attacker = $_[0];
  90.     my $target = $_[1];
  91.     disp("- attackDmg $attacker $target");
  92.     my $strength = $group{$attacker}{"number"} * $group{$attacker}{"attackdmg"};
  93.     disp("-- attackDmg Strength: $strength");
  94.     my $atktype = $group{$attacker}{"attacktype"};
  95.     disp("-- attackDmg Attack type: $atktype");
  96.     if($group{$target}{"weaknesses"} =~ /$atktype/) { disp("-- attackDmg Target is weak!"); $strength = $strength * 2; }
  97.     elsif($group{$target}{"immuneto"} =~ /$atktype/) { disp("-- attackDmg Target has immunity"); $strength = 0; }
  98.     disp("-- attackDmg Final strength: $strength");
  99.     return $strength;
  100. }
  101.  
  102. sub selectTargets {
  103.     for(my $tar = 0; $tar < $howmanygroups; $tar++) { $group{$tar}{"targetted"} = 0; $group{$tar}{"targetthisturn"} = -1; }
  104.     for(my $s = 0; $s <= $#selectionorder; $s++) {
  105.         my $i = $selectionorder[$s][2];
  106.         my $team = $group{$i}{"team"};
  107.         disp("- selectTargets with ".$i." (team ".$team.")");
  108.         my $highestDmg = 0; my $highestIndex = -1;
  109.         for(my $tar = 0; $tar < $howmanygroups; $tar++) {
  110.             if($group{$tar}{"team"} != $team) {
  111.                 if($group{$tar}{"number"} > 0) {
  112.                     if($group{$tar}{"targetted"} == 0) {
  113.                         my $dmg = attackDmg($i,$tar);
  114.                         disp("-- selectTargets ".$tar." is a potential target. Dmg: ".$dmg);
  115.                         if($dmg > $highestDmg || $highestIndex == -1) { # If new best damage, no contest
  116.                             disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": new record");
  117.                             $highestDmg = $dmg;
  118.                             $highestIndex = $tar;
  119.                         } elsif($dmg == $highestDmg) { # First tie
  120.                             disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": tie!");
  121.                             if($group{$tar}{"number"} * $group{$tar}{"attackdmg"} > $group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"}) { # If new group has higher effective power, target this one
  122.                                 disp("-- selectTargets Comparing old record's effective power ".($group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"})." to new ".($group{$tar}{"number"} * $group{$tar}{"attackdmg"}).": new record");
  123.                                 $highestDmg = $dmg;
  124.                                 $highestIndex = $tar;
  125.                             } elsif($group{$tar}{"number"} * $group{$tar}{"attackdmg"} == $group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"}) { # Second tie
  126.                                 disp("-- selectTargets Comparing old record's effective power ".($group{$highestIndex}{"number"} * $group{$highestIndex}{"attackdmg"})." to new ".($group{$tar}{"number"} * $group{$tar}{"attackdmg"}).": tie!");
  127.                                 if($group{$tar}{"initiative"} > $group{$highestIndex}{"initiative"}) { # If new group has higher initiative, target this one
  128.                                     disp("-- selectTargets Comparing old record's initiative ".$group{$highestIndex}{"initiative"}." to new ".$group{$tar}{"initiative"}.": new record");
  129.                                     $highestDmg = $dmg;
  130.                                     $highestIndex = $tar;
  131.                                 } else { disp("-- selectTargets Comparing old record's initiative ".$group{$highestIndex}{"initiative"}." to new ".$group{$tar}{"initiative"}.": not beaten"); }
  132.                             } 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"); }
  133.                         } else { disp("-- selectTargets Comparing old record ".$highestDmg." to new ".$dmg.": not beaten"); }
  134.                     } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": already a target");   }
  135.                 } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": no more troops"); }
  136.             } else { disp("- selectTargets ".$tar." could not be selected as a target for ".$i.": same team!"); }
  137.         }
  138.         disp("- selectTargets ".$i." has selected ".$highestIndex);
  139.         $group{$i}{"targetthisturn"} = $highestIndex;
  140.         $group{$highestIndex}{"targetted"} = 1;
  141.     }
  142. }
  143.  
  144. my @attackorder;
  145. sub defineAttackOrder {
  146.     @attackorder = ();
  147.     #disp("----- Attack order:");
  148.     for(my $i = $howmanygroups; $i >= 0; $i--) {
  149.         for(my $j = 0; $j < $howmanygroups; $j++) {
  150.             if($group{$j}{"initiative"} == $i) {
  151.                 if($group{$j}{"number"} > 0) { push(@attackorder,$j); }
  152.                 last;
  153.             }
  154.         }
  155.     }
  156.     #disp("--------------------");
  157. }
  158.  
  159. sub didSomeoneWin {
  160.     my @teams; $teams[1] = 0; $teams[2] = 0;
  161.     for(my $i = 0; $i < $howmanygroups; $i++) {
  162.         if($group{$i}{"number"} > 0) {
  163.             $teams[$group{$i}{"team"}]++;
  164.         }
  165.     }
  166.     if($teams[1] == 0) { return 2 }
  167.     elsif($teams[2] == 0 ) { return 1 }
  168.     else { return 0; }
  169. }
  170.  
  171. my $round = 1;
  172.  
  173. while(didSomeoneWin() == 0) { # Main loop
  174.     disp("!!! Round ".$round." !!!\n");
  175.     defineSelectionOrder();
  176.     selectTargets();
  177.     defineAttackOrder();
  178.     for(my $i = 0; $i <= $#attackorder; $i++) {
  179.         my $attacker = $attackorder[$i];
  180.         disp("Main loop: ".$attacker." will attack");
  181.         if($group{$attacker}{"number"} > 0 && $group{$attacker}{"targetthisturn"} > -1) {
  182.             my $defender = $group{$attacker}{"targetthisturn"};
  183.             my $dmg = attackDmg($attacker,$defender);
  184.             disp("Main loop: ".$attacker." will attack ".$defender." for ".$dmg);
  185.             if($dmg >= $group{$defender}{"hp"} * $group{$defender}{"number"} ) {
  186.                 disp("Main loop: after ".$attacker."'s attack, defender ".$defender." has no more troops");
  187.                 $group{$defender}{"number"} = 0;
  188.                 }
  189.             else {
  190.                 my $dead = int($dmg / $group{$defender}{"hp"});
  191.                 $group{$defender}{"number"} = $group{$defender}{"number"} - $dead;
  192.                 disp("Main loop: after ".$attacker."'s attack, defender ".$defender." loses ".$dead." troops. Remaining: ".$group{$defender}{"number"});
  193.             }
  194.         } else { disp("Main loop: ".$attacker." could not attack"); }
  195.     }
  196.     $round++;
  197. }
  198.  
  199. print("Situation at the end:\n");
  200. allInfo();
  201.  
  202. for(my $i = 0; $i < $howmanygroups; $i++) {
  203.     $total += $group{$i}{"number"};
  204. }
  205.  
  206. print("Total: ".$total);
  207.  
  208. printf("[Ran in %0.1f milliseconds]\n", (time() - $starttime) * 1000);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement