Advertisement
Guest User

AoC day 11 part 2

a guest
Dec 11th, 2016
924
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.76 KB | None | 0 0
  1. internal static void Solve2()
  2. {
  3.     // Promethium: 0
  4.     // Cobalt: 1
  5.     // Curium: 2
  6.     // Ruthenium: 3
  7.     // Plutonium: 4
  8.     // Elerium: 5
  9.     // Dilithium: 6
  10.     // First byte is microchips on floor 0, second is generators on floor 0, third is microchips on floor 1, etc.
  11.     // Initial state:
  12.     // Floor 1: PRG, PRM, EG, EM, DG, DM
  13.     // Floor 2: COG, CUG, RUG, PLG
  14.     // Floor 3: COM, CUM, RUM, PLM
  15.     ulong initialState = 0b00000000_00000000_00000000_00011110_00011110_00000000_01100001_01100001;
  16.  
  17.     int[] indices = { 0, 1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 12, 13, 14, -1 };
  18.  
  19.     Queue<State> queue = new Queue<State>();
  20.     HashSet<State> seen = new HashSet<State>();
  21.     queue.Enqueue(new State(0, initialState, 0));
  22.     seen.Add(queue.Peek());
  23.  
  24.     int prevSteps = 0;
  25.     while (queue.Count > 0)
  26.     {
  27.         var curState = queue.Dequeue();
  28.  
  29.         for (int idir = 0; idir < 2; idir++)
  30.         {
  31.             int dir = idir == 0 ? 1 : -1;
  32.             if (curState.Elevator == 0 && dir == -1)
  33.                 continue;
  34.             if (curState.Elevator == 3 && dir == 1)
  35.                 continue;
  36.  
  37.             for (int i = 0; i < indices.Length - 1; i++)
  38.             {
  39.                 for (int j = i + 1; j < indices.Length; j++)
  40.                 {
  41.                     State? newState = curState.Move(dir, indices[i], indices[j]);
  42.                     if (newState.HasValue && seen.Add(newState.Value))
  43.                     {
  44.                         if ((newState.Value.FloorItems & 0b11111111_11111111_11111111_11111111_11111111_11111111) == 0)
  45.                         {
  46.                             Console.WriteLine("Steps: {0}", newState.Value.Steps);
  47.                             return;
  48.                         }
  49.  
  50.                         if (newState.Value.Steps > prevSteps)
  51.                         {
  52.                             prevSteps = newState.Value.Steps;
  53.                             Console.WriteLine(prevSteps);
  54.                         }
  55.  
  56.                         queue.Enqueue(newState.Value);
  57.                     }
  58.                 }
  59.             }
  60.         }
  61.     }
  62.  
  63.     Console.WriteLine("No more items");
  64. }
  65.  
  66. private struct State
  67. {
  68.     public State(int elevator, ulong floorItems, int steps)
  69.     {
  70.         Elevator = elevator;
  71.         FloorItems = floorItems;
  72.         Steps = steps;
  73.     }
  74.  
  75.     public int Elevator { get; }
  76.     public ulong FloorItems { get; }
  77.     public int Steps { get; }
  78.  
  79.     public State? Move(int dir, int item1, int item2 = -1)
  80.     {
  81.         if (item2 != -1 &&
  82.             ((item1 >= 8 && item2 < 8 && item2 != item1 - 8) ||
  83.              (item1 < 8 && item2 >= 8 && item1 != item2 - 8)))
  84.         {
  85.             // One is microchip, other is generator, and they are not of same kind
  86.             return null;
  87.         }
  88.  
  89.         int newElevator = Elevator + dir;
  90.  
  91.         ulong oldBit1 = 1ul << (Elevator * 16 + item1);
  92.         ulong oldBit2 = item2 == -1 ? 0 : 1ul << (Elevator * 16 + item2);
  93.  
  94.         ulong newBit1 = 1ul << (newElevator * 16 + item1);
  95.         ulong newBit2 = item2 == -1 ? 1 : 1ul << (newElevator * 16 + item2);
  96.  
  97.         if ((FloorItems & oldBit1) == 0 ||
  98.             item2 != -1 && (FloorItems & oldBit2) == 0)
  99.             return null; // Items not on floor
  100.  
  101.         ulong newFloorItems = FloorItems;
  102.         newFloorItems &= ~oldBit1;
  103.         if (item2 != -1)
  104.             newFloorItems &= ~oldBit2;
  105.  
  106.         newFloorItems |= newBit1;
  107.         if (item2 != -1)
  108.             newFloorItems |= newBit2;
  109.  
  110.         for (int i = 0; i < 4; i++)
  111.         {
  112.             int microchips = (int)((newFloorItems >> (i * 16)) & 0xFF);
  113.             int generators = (int)((newFloorItems >> (i * 16 + 8)) & 0xFF);
  114.  
  115.             // If a floor contains a generator and a chip of different kinds,
  116.             // the chip must be protected to avoid frying.
  117.             // We can remove the microchips that are protected with & ~generators.
  118.             int unprotected = microchips & ~generators;
  119.             // Now if there are any generators too, then the unprotected ones would be fried.
  120.             if (unprotected != 0 && generators != 0)
  121.                 return null;
  122.         }
  123.  
  124.         return new State(newElevator, newFloorItems, Steps + 1);
  125.     }
  126.  
  127.     public bool Equals(State other)
  128.     {
  129.         return Elevator == other.Elevator && FloorItems == other.FloorItems;
  130.     }
  131.  
  132.     public override bool Equals(object obj)
  133.     {
  134.         if (ReferenceEquals(null, obj))
  135.             return false;
  136.         if (ReferenceEquals(this, obj))
  137.             return true;
  138.         if (obj.GetType() != GetType())
  139.             return false;
  140.         return Equals((State)obj);
  141.     }
  142.  
  143.     public override int GetHashCode()
  144.     {
  145.         return unchecked((Elevator * 397) ^ FloorItems.GetHashCode());
  146.     }
  147. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement