Merge remote-tracking branch '2019/main'
This commit is contained in:
		
						commit
						c27c60ce9a
					
				|  | @ -0,0 +1,4 @@ | ||||||
|  | bin/ | ||||||
|  | zig-out/ | ||||||
|  | zig-cache/ | ||||||
|  | target/ | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | .PHONY: bench-build bench-rebuild bench | ||||||
|  | 
 | ||||||
|  | bench-build: | ||||||
|  | 	hyperfine -p 'rm -f bin/main' -c 'rm -f bin/main' 'rustc --out-dir bin/ main.rs' | ||||||
|  | 	hyperfine -p 'rm -rf zig-out/ zig-cache/' -c 'rm -rf zig-out/ zig-cache/' '~/src/misc/zig/build/zig build' | ||||||
|  | 
 | ||||||
|  | bench-rebuild: | ||||||
|  | 	hyperfine 'rustc --out-dir bin/ main.rs' | ||||||
|  | 	hyperfine '~/src/misc/zig/build/zig build' | ||||||
|  | 
 | ||||||
|  | bench: | ||||||
|  | 	hyperfine -p 'rustc --out-dir bin/ main.rs' ./bin/main | ||||||
|  | 	hyperfine -p '~/src/misc/zig/build/zig build' ./zig-out/bin/day1 | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | const std = @import("std"); | ||||||
|  | 
 | ||||||
|  | pub fn build(b: *std.build.Builder) void { | ||||||
|  |     // Standard target options allows the person running `zig build` to choose | ||||||
|  |     // what target to build for. Here we do not override the defaults, which | ||||||
|  |     // means any target is allowed, and the default is native. Other options | ||||||
|  |     // for restricting supported target set are available. | ||||||
|  |     const target = b.standardTargetOptions(.{}); | ||||||
|  | 
 | ||||||
|  |     // Standard release options allow the person running `zig build` to select | ||||||
|  |     // between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. | ||||||
|  |     const mode = b.standardReleaseOptions(); | ||||||
|  | 
 | ||||||
|  |     const exe = b.addExecutable("day1", "src/main.zig"); | ||||||
|  |     exe.setTarget(target); | ||||||
|  |     exe.setBuildMode(mode); | ||||||
|  |     exe.install(); | ||||||
|  | 
 | ||||||
|  |     const run_cmd = exe.run(); | ||||||
|  |     run_cmd.step.dependOn(b.getInstallStep()); | ||||||
|  |     if (b.args) |args| { | ||||||
|  |         run_cmd.addArgs(args); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const run_step = b.step("run", "Run the app"); | ||||||
|  |     run_step.dependOn(&run_cmd.step); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,100 @@ | ||||||
|  | 85644 | ||||||
|  | 52584 | ||||||
|  | 72349 | ||||||
|  | 83834 | ||||||
|  | 56593 | ||||||
|  | 108492 | ||||||
|  | 94585 | ||||||
|  | 97733 | ||||||
|  | 62732 | ||||||
|  | 103113 | ||||||
|  | 133259 | ||||||
|  | 132647 | ||||||
|  | 52460 | ||||||
|  | 51299 | ||||||
|  | 115749 | ||||||
|  | 121047 | ||||||
|  | 69451 | ||||||
|  | 54737 | ||||||
|  | 62738 | ||||||
|  | 116686 | ||||||
|  | 57293 | ||||||
|  | 97273 | ||||||
|  | 128287 | ||||||
|  | 139440 | ||||||
|  | 97583 | ||||||
|  | 130263 | ||||||
|  | 79307 | ||||||
|  | 118198 | ||||||
|  | 82514 | ||||||
|  | 70679 | ||||||
|  | 64485 | ||||||
|  | 119346 | ||||||
|  | 136281 | ||||||
|  | 114724 | ||||||
|  | 73580 | ||||||
|  | 76314 | ||||||
|  | 126198 | ||||||
|  | 97635 | ||||||
|  | 114655 | ||||||
|  | 104195 | ||||||
|  | 99469 | ||||||
|  | 70251 | ||||||
|  | 82815 | ||||||
|  | 79531 | ||||||
|  | 58135 | ||||||
|  | 80625 | ||||||
|  | 73106 | ||||||
|  | 139806 | ||||||
|  | 138478 | ||||||
|  | 136605 | ||||||
|  | 111472 | ||||||
|  | 149915 | ||||||
|  | 95928 | ||||||
|  | 126905 | ||||||
|  | 70496 | ||||||
|  | 147999 | ||||||
|  | 148501 | ||||||
|  | 114025 | ||||||
|  | 75716 | ||||||
|  | 113473 | ||||||
|  | 95390 | ||||||
|  | 104466 | ||||||
|  | 138715 | ||||||
|  | 53053 | ||||||
|  | 79502 | ||||||
|  | 98601 | ||||||
|  | 115139 | ||||||
|  | 122315 | ||||||
|  | 88402 | ||||||
|  | 124332 | ||||||
|  | 140107 | ||||||
|  | 50912 | ||||||
|  | 104885 | ||||||
|  | 142005 | ||||||
|  | 145938 | ||||||
|  | 118556 | ||||||
|  | 101858 | ||||||
|  | 51142 | ||||||
|  | 94100 | ||||||
|  | 99421 | ||||||
|  | 84544 | ||||||
|  | 137234 | ||||||
|  | 126374 | ||||||
|  | 107333 | ||||||
|  | 82439 | ||||||
|  | 125373 | ||||||
|  | 51212 | ||||||
|  | 99358 | ||||||
|  | 82821 | ||||||
|  | 89913 | ||||||
|  | 67513 | ||||||
|  | 136907 | ||||||
|  | 133707 | ||||||
|  | 139988 | ||||||
|  | 96914 | ||||||
|  | 130672 | ||||||
|  | 66474 | ||||||
|  | 120729 | ||||||
|  | 50131 | ||||||
|  | 67475 | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | fn main() { | ||||||
|  |     let contents = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     let it = contents.split("\n"); | ||||||
|  |     let mut sum: u64 = 0; | ||||||
|  |     let mut sum2: u64 = 0; | ||||||
|  |     for val in it { | ||||||
|  |         if val == "" { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         let mut x = val.parse::<u64>().unwrap(); | ||||||
|  |         x /= 3; | ||||||
|  |         x -= 2; | ||||||
|  |         sum += x; | ||||||
|  |         sum2 += x; | ||||||
|  |         while x > 0 { | ||||||
|  |             x /= 3; | ||||||
|  |             if x < 2 { | ||||||
|  |                 x = 0; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 x -= 2; | ||||||
|  |             } | ||||||
|  |             sum2 += x; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("[Part 1] The sum is {}", sum); | ||||||
|  |     println!("[Part 2] The sum is {}", sum2); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | const std = @import("std"); | ||||||
|  | 
 | ||||||
|  | pub fn main() anyerror!void { | ||||||
|  |     var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); | ||||||
|  |     defer arena.deinit(); | ||||||
|  |     const alloc = &arena.allocator; | ||||||
|  | 
 | ||||||
|  |     // Read our input | ||||||
|  |     var f = try std.fs.cwd().openFile("input", .{}); | ||||||
|  |     defer f.close(); | ||||||
|  |     var contents = try f.readToEndAlloc(alloc, std.math.maxInt(u32)); | ||||||
|  |     defer alloc.free(contents); | ||||||
|  | 
 | ||||||
|  |     var it = std.mem.tokenize(contents, "\n"); | ||||||
|  |     var sum: u64 = 0; | ||||||
|  |     var sum2: u64 = 0; | ||||||
|  |     while (it.next()) |v| { | ||||||
|  |         var val: u64 = try std.fmt.parseInt(u64, v, 10); | ||||||
|  |         val /= 3; | ||||||
|  |         val -= 2; | ||||||
|  |         sum += val; | ||||||
|  |         sum2 += val; | ||||||
|  |         while (val > 0) { | ||||||
|  |             val /= 3; | ||||||
|  |             if (val < 2) { | ||||||
|  |                 val = 0; | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 val -= 2; | ||||||
|  |             } | ||||||
|  |             sum2 += val; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     std.log.info("[Part 1] Sum: {}", .{sum}); | ||||||
|  |     std.log.info("[Part 2] Sum: {}", .{sum2}); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day2" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "day2" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 1,0,0,3,1,1,2,3,1,3,4,3,1,5,0,3,2,1,10,19,1,9,19,23,1,13,23,27,1,5,27,31,2,31,6,35,1,35,5,39,1,9,39,43,1,43,5,47,1,47,5,51,2,10,51,55,1,5,55,59,1,59,5,63,2,63,9,67,1,67,5,71,2,9,71,75,1,75,5,79,1,10,79,83,1,83,10,87,1,10,87,91,1,6,91,95,2,95,6,99,2,99,9,103,1,103,6,107,1,13,107,111,1,13,111,115,2,115,9,119,1,119,6,123,2,9,123,127,1,127,5,131,1,131,5,135,1,135,5,139,2,10,139,143,2,143,10,147,1,147,5,151,1,151,2,155,1,155,13,0,99,2,14,0,0 | ||||||
|  | @ -0,0 +1,105 @@ | ||||||
|  | fn main() { | ||||||
|  |     let contents = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     let it = contents.split(","); | ||||||
|  |     let mut program = Vec::new(); | ||||||
|  |     for val in it { | ||||||
|  |         if val.ends_with('\n') { | ||||||
|  |             let mut s = String::from(val); | ||||||
|  |             s.pop(); | ||||||
|  |             program.push(s.parse::<i32>().unwrap()); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             program.push(val.parse::<i32>().unwrap()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Create a copy of the memory to refresh from
 | ||||||
|  |     let backup = program.clone(); | ||||||
|  | 
 | ||||||
|  |     // Modify state for part 1
 | ||||||
|  |     program[1] = 12; | ||||||
|  |     program[2] = 2; | ||||||
|  |     simulate(&mut program); | ||||||
|  |     println!("[Part 1] The value at position 0 is: {}", program[0]); | ||||||
|  | 
 | ||||||
|  |     let mut noun = 0; | ||||||
|  |     while noun < 100 { | ||||||
|  |         let mut verb = 0; | ||||||
|  |         while verb < 100 { | ||||||
|  |             program = backup.clone(); | ||||||
|  |             program[1] = noun; | ||||||
|  |             program[2] = verb; | ||||||
|  |             simulate(&mut program); | ||||||
|  |             //println!("Noun {}, verb {}: {}", noun, verb, program[0]);
 | ||||||
|  |             if program[0] == 19690720 { | ||||||
|  |                 println!("[Part 2] noun {}, verb {}, sum {}", noun, verb, 100*noun+verb); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             verb += 1; | ||||||
|  |         } | ||||||
|  |         noun += 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn simulate(v: &mut Vec<i32>) { | ||||||
|  |     let mut pos = 0; | ||||||
|  |     loop { | ||||||
|  |         let code = v[pos]; | ||||||
|  |         if code == 1 { | ||||||
|  |             let i1 = v[pos+1] as usize; | ||||||
|  |             let i2 = v[pos+2] as usize; | ||||||
|  |             let idest = v[pos+3] as usize; | ||||||
|  |             v[idest] = v[i1] + v[i2]; | ||||||
|  |             pos += 4; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         else if code == 2 { | ||||||
|  |             let i1 = v[pos+1] as usize; | ||||||
|  |             let i2 = v[pos+2] as usize; | ||||||
|  |             let idest = v[pos+3] as usize; | ||||||
|  |             v[idest] = v[i1] * v[i2]; | ||||||
|  |             pos += 4; | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         else if code == 99 { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             panic!("Unknown opcode"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |     #[test] | ||||||
|  |     fn test_op_1() { | ||||||
|  |         let mut program = vec![1, 0, 0, 0, 99]; | ||||||
|  |         simulate(&mut program); | ||||||
|  |         assert_eq!(program[0], 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_op_2() { | ||||||
|  |         let mut program = vec![2, 3, 0, 3, 99]; | ||||||
|  |         simulate(&mut program); | ||||||
|  |         assert_eq!(program[3], 6); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_case_3() { | ||||||
|  |         let mut program = vec![2,4,4,5,99,0]; | ||||||
|  |         simulate(&mut program); | ||||||
|  |         assert_eq!(program[program.len() - 1], 9801); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_case_4() { | ||||||
|  |         let mut program = vec![1,1,1,4,99,5,6,0,99]; | ||||||
|  |         simulate(&mut program); | ||||||
|  |         assert_eq!(program[0], 30); | ||||||
|  |         assert_eq!(program[4], 2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day3" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "day3" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | R990,U944,L921,U993,L64,U29,R899,D406,R841,U716,L32,U658,L830,D481,L441,U491,L687,D847,L459,U920,R165,U224,L896,D868,L191,U877,L909,U467,R798,U132,R234,U49,R484,U911,R108,D308,R867,U350,L404,U107,L84,U668,R850,U470,L182,U93,R284,U999,L664,U110,R650,D189,R540,D112,R794,U999,R871,D829,L549,U988,R654,D411,R323,D774,R529,U275,L909,U936,R122,D922,L331,U813,L748,U770,R511,D892,L770,U318,R661,U823,R210,D393,L694,U929,L76,D619,R395,U651,R526,U145,R851,U112,R73,D89,R17,U929,R807,U87,R764,D158,L820,U803,L785,D205,L828,D271,L839,D482,L797,U338,R322,D633,L292,U16,R627,U19,R548,U516,L384,U83,R256,U937,R404,U322,R671,D543,L412,U446,R238,U246,L794,D750,L34,U317,L994,U874,L247,D20,R491,U834,L498,D987,R2,U175,R452,U168,R495,D183,R201,U532,L192,U984,L566,D471,L704,D2,L776,U5,R911,U308,R763,D555,R458,D439,L968,D78,R549,D583,R289,D355,L503,D871,L881,U516,L507,D551,R711,U702,L308,D905,L408,U932,L884,U218,L158,D562,L200,D114,R673,U448,R887,U181,R247,U329,L965,U495,L329,D162,L265,D389,R419,U435,R258,U146,R208,D184,R730,D19,L78,D886,R472,D350,R484,U392,L542,U601,L202,U974,L310,U52,L537,U597,L163,D655,R928,U269,L926,D790,L513,U441,L90,U581,L211,U871,R603,D130,L220,U459,L933,U648,R721,U642,R301,U537,L858,D777,R823,U14,R820,D218,L96,D318,L206,U280,R887,D241,L752,U828,R354,U864,R844,D872,L728,D298,L234,U695,R434,D94,R905,D592,L32,D860,R680,D197,R886,U760,L232,U916,L452,U248,R715,D773,R867,U77,R751,D36,R565,U897,R782,U931,R546,U261,R920,D296,R451,U258,L394,U965,R912,D593,L990 | ||||||
|  | L994,U515,R163,U863,L343,U162,L875,D92,L483,D601,R79,D761,L389,U167,L145,U145,L247,U886,R61,U820,L584,D239,R402,U805,R956,U126,R615,D322,R431,D460,R397,D511,R805,D177,L778,U296,R599,U759,R40,U1,L422,U751,R94,U401,R504,U940,L564,U24,R595,U944,R815,U672,R787,D854,R579,D604,L62,U670,L516,U199,L639,D919,L485,U655,R391,U669,R772,D34,R868,D12,L108,U295,R701,D603,R493,U927,R29,D34,R499,U111,L87,U190,R884,D658,R474,D166,R921,U698,R592,U25,R710,D398,L26,U696,L432,D887,R469,U656,L428,D188,L543,D150,R160,U543,R743,U692,R618,D148,R956,U753,L175,D789,R897,U305,L137,D914,R330,D780,R744,D473,L754,U482,L975,D413,L698,U656,L177,U419,R13,D827,L67,D800,R369,U97,L34,D588,L41,D760,L164,U224,L921,D311,R489,U956,R277,U180,R724,U748,R785,U826,L426,D957,R303,U16,L729,U224,L712,U43,L280,D648,R987,D941,R154,D581,R876,U615,L480,D103,R636,D276,R948,U89,R434,D212,R837,D295,R532,D390,R374,D926,R911,D110,R258,U83,L955,U747,L925,D366,R571,U241,R628,D344,R919,U117,R337,D683,L720,U261,L124,D545,R979,D601,L906,D324,R441,U678,L978,U744,L472,D217,R799,U740,L77,U964,L278,U497,R441,U21,L37,U319,L24,D211,L44,U459,R35,D609,R900,D538,R397,D776,R629,D860,R519,D340,R168,U603,R46,U889,R897,D442,R997,U705,L82,D963,R941,U701,L347,D824,R269,U891,L569,D558,L867,U145,R121,D369,R542,U227,L198,U863,L755,U273,L734,D233,R578,U67,L821,U600,L203,D234,R695,U819,L639,D700,R295,D129,L612,U157,R212,U536,L968,U562,L999,D391,L231,U262,R334,D967,R463,U748,R842,D500,R860,U856,R263,D633,R460,D337,L880,U146,R910 | ||||||
|  | @ -0,0 +1,178 @@ | ||||||
|  | use std::collections::HashSet; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let mut contents = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     let mut it = contents.split("\n"); | ||||||
|  |     let mut line_a: HashSet<Point> = HashSet::new(); | ||||||
|  |     let mut line_b: HashSet<Point> = HashSet::new(); | ||||||
|  |     match it.next() { | ||||||
|  |         Some(v) => get_line_points_from_str(&mut line_a, &v), | ||||||
|  |         None    => panic!(), | ||||||
|  |     } | ||||||
|  |     match it.next() { | ||||||
|  |         Some(v) => { | ||||||
|  |             let s = String::from(v); | ||||||
|  |             get_line_points_from_str(&mut line_b, &s); | ||||||
|  |         }, | ||||||
|  |         None    => panic!(), | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Some possible approaches
 | ||||||
|  |     // my first thought was to do the following
 | ||||||
|  |     //   1) collect all points for line_a and line_b
 | ||||||
|  |     //   2) create a pool of intersecting points
 | ||||||
|  |     //   3) for all the intersecting points, which is
 | ||||||
|  |     //   closest to the origin in manhattan distance
 | ||||||
|  |     //
 | ||||||
|  |     // this is pretty easy, but seems like it would be
 | ||||||
|  |     // memory hungry and doesn't scale to large lines
 | ||||||
|  |     // bonus: rust HashSets (wrappers around HashMap)
 | ||||||
|  |     // a union method to facilitate this task.
 | ||||||
|  |     //
 | ||||||
|  |     // another thought I had was to find and use some
 | ||||||
|  |     // sort of math things to compare to pair of line
 | ||||||
|  |     // segments to see if they intersect, and if so - where.
 | ||||||
|  | 
 | ||||||
|  |     let mut closest_point: Point = Point {x: 0, y: 0}; | ||||||
|  |     let mut closest_distance = i32::MAX; | ||||||
|  |     let mut intersects: HashSet<Point> = HashSet::new(); | ||||||
|  |     for p in line_a.intersection(&line_b) { | ||||||
|  |         if p.x == 0 && p.y == 0 { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         intersects.insert(Point {x: p.x, y: p.y}); | ||||||
|  |         let distance = p.x.abs() + p.y.abs(); | ||||||
|  |         //println!("Intersection: {},{} distance {}",
 | ||||||
|  |         //         p.x, p.y, distance);
 | ||||||
|  |         if distance < closest_distance { | ||||||
|  |             closest_point = Point {x: p.x, y: p.y}; | ||||||
|  |             closest_distance = distance; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("[Part 1] Closest intersection {} away at {},{}", | ||||||
|  |              closest_distance, closest_point.x, closest_point.y); | ||||||
|  | 
 | ||||||
|  |     // We replay the get_line_poionts_from_str, but instead
 | ||||||
|  |     // when we reach one of the intersections we can add
 | ||||||
|  |     // Point, steps into a result set.
 | ||||||
|  |     let mut line_a_steps_to_intersect: HashMap<Point, u64> = HashMap::new(); | ||||||
|  |     let mut line_b_steps_to_intersect: HashMap<Point, u64> = HashMap::new(); | ||||||
|  |     contents = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     it = contents.split("\n"); | ||||||
|  |     match it.next() { | ||||||
|  |         Some(v) => get_steps_to_intersections(&intersects, v, | ||||||
|  |         &mut line_a_steps_to_intersect), | ||||||
|  |         None    => panic!(), | ||||||
|  |     } | ||||||
|  |     match it.next() { | ||||||
|  |         Some(v) => get_steps_to_intersections(&intersects, v, | ||||||
|  |         &mut line_b_steps_to_intersect), | ||||||
|  |         None    => panic!(), | ||||||
|  |     } | ||||||
|  |     let mut step_sum = u64::MAX; | ||||||
|  |     let iit = intersects.iter(); | ||||||
|  |     for p in iit { | ||||||
|  |         let new_sum = line_a_steps_to_intersect.get(&p).unwrap() | ||||||
|  |             + line_b_steps_to_intersect.get(&p).unwrap(); | ||||||
|  |         if new_sum < step_sum { | ||||||
|  |             step_sum = new_sum; | ||||||
|  |             closest_point = Point {x: p.x, y: p.y}; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("[Part 2] Intersection {},{} is {} steps away", | ||||||
|  |              closest_point.x, closest_point.y, step_sum); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn get_steps_to_intersections(points: &HashSet<Point>, source: &str, map: &mut HashMap<Point, u64>) { | ||||||
|  |     let mut x = 0; | ||||||
|  |     let mut y = 0; | ||||||
|  |     let mut total_steps = 0; | ||||||
|  |     let lit = source.split(","); | ||||||
|  |     for val in lit { | ||||||
|  |         let dir = val.chars().nth(0).unwrap(); | ||||||
|  |         let mut dx = 0; | ||||||
|  |         let mut dy = 0; | ||||||
|  |         let v = val[1..].parse::<i32>().unwrap(); | ||||||
|  |         match dir { | ||||||
|  |             'U' => dy = 1, | ||||||
|  |             'D' => dy = -1, | ||||||
|  |             'L' => dx = -1, | ||||||
|  |             'R' => dx = 1, | ||||||
|  |             _   => panic!(), | ||||||
|  |         } | ||||||
|  |         let mut needed_steps = 0; | ||||||
|  |         if dx != 0 { | ||||||
|  |             needed_steps = v; | ||||||
|  |             needed_steps = needed_steps.abs(); | ||||||
|  |         } | ||||||
|  |         if dy != 0 { | ||||||
|  |             needed_steps = v; | ||||||
|  |             needed_steps = needed_steps.abs(); | ||||||
|  |         } | ||||||
|  |         let mut step = 0; | ||||||
|  |         while step < needed_steps { | ||||||
|  |             x += dx; | ||||||
|  |             y += dy; | ||||||
|  |             total_steps += 1; | ||||||
|  |             let p = Point {x: x, y: y}; | ||||||
|  |             if points.contains(&p) { | ||||||
|  |                 //println!("Inserting intersection {},{} at {} steps",
 | ||||||
|  |                 //p.x, p.y, total_steps);
 | ||||||
|  |                 map.insert(p, total_steps); | ||||||
|  |             } | ||||||
|  |             step += 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn get_line_points_from_str(points: &mut HashSet<Point>, source: &str) { | ||||||
|  |     let mut x = 0; | ||||||
|  |     let mut y = 0; | ||||||
|  |     points.insert(Point { x: x, y: y }); | ||||||
|  |     let lit = source.split(","); | ||||||
|  |     for val in lit { | ||||||
|  |         let dir = val.chars().nth(0).unwrap(); | ||||||
|  |         let mut dx = 0; | ||||||
|  |         let mut dy = 0; | ||||||
|  |         let v = val[1..].parse::<i32>().unwrap(); | ||||||
|  |         match dir { | ||||||
|  |             'U' => dy = 1, | ||||||
|  |             'D' => dy = -1, | ||||||
|  |             'L' => dx = -1, | ||||||
|  |             'R' => dx = 1, | ||||||
|  |             _   => panic!(), | ||||||
|  |         } | ||||||
|  |         let mut needed_steps = 0; | ||||||
|  |         if dx != 0 { | ||||||
|  |             needed_steps = v; | ||||||
|  |             needed_steps = needed_steps.abs(); | ||||||
|  |         } | ||||||
|  |         if dy != 0 { | ||||||
|  |             needed_steps = v; | ||||||
|  |             needed_steps = needed_steps.abs(); | ||||||
|  |         } | ||||||
|  |         //println!("Walking from {},{} {}{} (step {},{} {} times)",
 | ||||||
|  |         //x, y, dir, v, dx, dy, needed_steps);
 | ||||||
|  |         let mut step = 0; | ||||||
|  |         while step < needed_steps { | ||||||
|  |             x += dx; | ||||||
|  |             y += dy; | ||||||
|  |             //println!("Adding {},{}", x, y);
 | ||||||
|  |             points.insert(Point {x: x, y: y}); | ||||||
|  |             step += 1; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(PartialEq, Eq, Hash)] | ||||||
|  | struct Point { | ||||||
|  |     x: i32, | ||||||
|  |     y: i32, | ||||||
|  | } | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | @ -0,0 +1,2 @@ | ||||||
|  | R8,U5,L5,D3 | ||||||
|  | U7,R6,D4,L4 | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day4" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "day4" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | @ -0,0 +1,101 @@ | ||||||
|  | fn main() { | ||||||
|  |     let min = [1, 9, 3, 6, 5, 1]; | ||||||
|  |     let max = [6, 4, 9, 7, 2, 9]; | ||||||
|  | 
 | ||||||
|  |     let mut matches = 0; | ||||||
|  |     let mut i = min.clone(); | ||||||
|  |     loop { | ||||||
|  |         // Check for a adjacents
 | ||||||
|  |         if i[0] == i[1] || | ||||||
|  |             i[1] == i[2] || | ||||||
|  |             i[2] == i[3] || | ||||||
|  |             i[3] == i[4] || | ||||||
|  |             i[4] == i[5] | ||||||
|  |         { | ||||||
|  |             // Check for incrementing
 | ||||||
|  |             if i[0] <= i[1] && | ||||||
|  |                 i[1] <= i[2] && | ||||||
|  |                 i[2] <= i[3] && | ||||||
|  |                 i[3] <= i[4] && | ||||||
|  |                 i[4] <= i[5] | ||||||
|  |             { | ||||||
|  |                 //println!("{:?} matches", i);
 | ||||||
|  |                 matches += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         let mut x = 5; | ||||||
|  |         loop { | ||||||
|  |             i[x] += 1; | ||||||
|  |             if i[x] >= 10 { | ||||||
|  |                 i[x] -= 10; | ||||||
|  |                 x -= 1; | ||||||
|  |                 continue
 | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if i[0] >= max[0] && | ||||||
|  |             i[1] >= max[1] && | ||||||
|  |             i[2] >= max[2] && | ||||||
|  |             i[3] >= max[3] && | ||||||
|  |             i[4] >= max[4] && | ||||||
|  |             i[5] >= max[5] { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("[Part 1] There are {} potential matches", matches); | ||||||
|  | 
 | ||||||
|  |     i = min.clone(); | ||||||
|  |     matches = 0; | ||||||
|  |     loop { | ||||||
|  |         // Check for incrementing
 | ||||||
|  |         if i[0] <= i[1] && | ||||||
|  |             i[1] <= i[2] && | ||||||
|  |             i[2] <= i[3] && | ||||||
|  |             i[3] <= i[4] && | ||||||
|  |             i[4] <= i[5] | ||||||
|  |         { | ||||||
|  |             // Check for groups
 | ||||||
|  |             let mut idx = 0; | ||||||
|  |             let mut has_two_chain = false; | ||||||
|  |             let mut chain_size = 1; | ||||||
|  |             while idx < 5 { | ||||||
|  |                 if i[idx] == i[idx+1] { | ||||||
|  |                     chain_size += 1; | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 else { | ||||||
|  |                     if chain_size == 2 { | ||||||
|  |                         has_two_chain = true; | ||||||
|  |                     } | ||||||
|  |                     chain_size = 1; | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             if chain_size == 2 { | ||||||
|  |                 has_two_chain = true; | ||||||
|  |             } | ||||||
|  |             if has_two_chain { | ||||||
|  |                 matches += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         let mut x = 5; | ||||||
|  |         loop { | ||||||
|  |             i[x] += 1; | ||||||
|  |             if i[x] >= 10 { | ||||||
|  |                 i[x] -= 10; | ||||||
|  |                 x -= 1; | ||||||
|  |                 continue
 | ||||||
|  |             } | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         if i[0] >= max[0] && | ||||||
|  |             i[1] >= max[1] && | ||||||
|  |             i[2] >= max[2] && | ||||||
|  |             i[3] >= max[3] && | ||||||
|  |             i[4] >= max[4] && | ||||||
|  |             i[5] >= max[5] { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("[Part 2] There are {} potential matches", matches); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day5" | ||||||
|  | version = "0.2.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "icc", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "icc" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | [package] | ||||||
|  | name = "day5" | ||||||
|  | version = "0.2.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | icc = { path = "../icc", version = "0.1.0"} | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 3,225,1,225,6,6,1100,1,238,225,104,0,1102,72,20,224,1001,224,-1440,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,1002,147,33,224,101,-3036,224,224,4,224,102,8,223,223,1001,224,5,224,1,224,223,223,1102,32,90,225,101,65,87,224,101,-85,224,224,4,224,1002,223,8,223,101,4,224,224,1,223,224,223,1102,33,92,225,1102,20,52,225,1101,76,89,225,1,117,122,224,101,-78,224,224,4,224,102,8,223,223,101,1,224,224,1,223,224,223,1102,54,22,225,1102,5,24,225,102,50,84,224,101,-4600,224,224,4,224,1002,223,8,223,101,3,224,224,1,223,224,223,1102,92,64,225,1101,42,83,224,101,-125,224,224,4,224,102,8,223,223,101,5,224,224,1,224,223,223,2,58,195,224,1001,224,-6840,224,4,224,102,8,223,223,101,1,224,224,1,223,224,223,1101,76,48,225,1001,92,65,224,1001,224,-154,224,4,224,1002,223,8,223,101,5,224,224,1,223,224,223,4,223,99,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,1105,0,99999,1105,227,247,1105,1,99999,1005,227,99999,1005,0,256,1105,1,99999,1106,227,99999,1106,0,265,1105,1,99999,1006,0,99999,1006,227,274,1105,1,99999,1105,1,280,1105,1,99999,1,225,225,225,1101,294,0,0,105,1,0,1105,1,99999,1106,0,300,1105,1,99999,1,225,225,225,1101,314,0,0,106,0,0,1105,1,99999,1107,677,226,224,1002,223,2,223,1005,224,329,101,1,223,223,7,677,226,224,102,2,223,223,1005,224,344,1001,223,1,223,1107,226,226,224,1002,223,2,223,1006,224,359,1001,223,1,223,8,226,226,224,1002,223,2,223,1006,224,374,101,1,223,223,108,226,226,224,102,2,223,223,1005,224,389,1001,223,1,223,1008,226,226,224,1002,223,2,223,1005,224,404,101,1,223,223,1107,226,677,224,1002,223,2,223,1006,224,419,101,1,223,223,1008,226,677,224,1002,223,2,223,1006,224,434,101,1,223,223,108,677,677,224,1002,223,2,223,1006,224,449,101,1,223,223,1108,677,226,224,102,2,223,223,1006,224,464,1001,223,1,223,107,677,677,224,102,2,223,223,1005,224,479,101,1,223,223,7,226,677,224,1002,223,2,223,1006,224,494,1001,223,1,223,7,677,677,224,102,2,223,223,1006,224,509,101,1,223,223,107,226,677,224,1002,223,2,223,1006,224,524,1001,223,1,223,1007,226,226,224,102,2,223,223,1006,224,539,1001,223,1,223,108,677,226,224,102,2,223,223,1005,224,554,101,1,223,223,1007,677,677,224,102,2,223,223,1006,224,569,101,1,223,223,8,677,226,224,102,2,223,223,1006,224,584,1001,223,1,223,1008,677,677,224,1002,223,2,223,1006,224,599,1001,223,1,223,1007,677,226,224,1002,223,2,223,1005,224,614,101,1,223,223,1108,226,677,224,1002,223,2,223,1005,224,629,101,1,223,223,1108,677,677,224,1002,223,2,223,1005,224,644,1001,223,1,223,8,226,677,224,1002,223,2,223,1006,224,659,101,1,223,223,107,226,226,224,102,2,223,223,1005,224,674,101,1,223,223,4,223,99,226 | ||||||
|  | @ -0,0 +1,29 @@ | ||||||
|  | use icc; | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let contents = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     let it = contents.split(","); | ||||||
|  |     let mut program = Vec::new(); | ||||||
|  |     for val in it { | ||||||
|  |         if val.ends_with('\n') { | ||||||
|  |             let mut s = String::from(val); | ||||||
|  |             s.pop(); | ||||||
|  |             program.push(s.parse::<i32>().unwrap()); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             program.push(val.parse::<i32>().unwrap()); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Create a copy of the memory to refresh from
 | ||||||
|  |     let backup = program.clone(); | ||||||
|  | 
 | ||||||
|  |     let mut output: i32 = 0; | ||||||
|  |     println!("Start part 1"); | ||||||
|  |     icc::simulate(&mut program, 1, &mut output); | ||||||
|  | 
 | ||||||
|  |     program = backup.clone(); | ||||||
|  |     println!("\nStart part 2"); | ||||||
|  |     icc::simulate(&mut program, 5, &mut output); | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day6" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "day6" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							|  | @ -0,0 +1,169 @@ | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | fn copy_to_array(a: &mut [char; 3], b: &str) { | ||||||
|  |     assert_eq!(b.len(), 3); | ||||||
|  |     let mut x = 0; | ||||||
|  |     for c in b.chars() { | ||||||
|  |         a[x] = c; | ||||||
|  |         x += 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     { | ||||||
|  |         let test_map = get_map_from_file("test"); | ||||||
|  |         assert_eq!(test_map.get("COM").unwrap().distance_to_com(&test_map), 0); | ||||||
|  |         assert_eq!(test_map.get("B").unwrap().distance_to_com(&test_map), 1); | ||||||
|  |         assert_eq!(test_map.get("D").unwrap().distance_to_com(&test_map), 3); | ||||||
|  |         assert_eq!(test_map.get("L").unwrap().distance_to_com(&test_map), 7); | ||||||
|  |         let f_parents = test_map.get("F").unwrap().parents(&test_map); | ||||||
|  |         assert_eq!(f_parents, vec!["E", "D", "C", "B", "COM"]); | ||||||
|  |         let l_parents = test_map.get("L").unwrap().parents(&test_map); | ||||||
|  |         assert_eq!(l_parents, vec!["K", "J", "E", "D", "C", "B", "COM"]); | ||||||
|  |         assert_eq!(first_common(f_parents, l_parents), "E"); | ||||||
|  |         let mut x: i32 = 0; | ||||||
|  |         for val in test_map.values() { | ||||||
|  |             x += val.distance_to_com(&test_map); | ||||||
|  |         } | ||||||
|  |         assert_eq!(x, 42); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let test_map2 = get_map_from_file("test2"); | ||||||
|  |         let you = test_map2.get("YOU").unwrap(); | ||||||
|  |         let san = test_map2.get("SAN").unwrap(); | ||||||
|  |         println!("{:?}", you); | ||||||
|  |         println!("{:?}", san); | ||||||
|  |         println!("{:?}", you.parents(&test_map2)); | ||||||
|  |         println!("{:?}", san.parents(&test_map2)); | ||||||
|  |         let parent = first_common(you.parents(&test_map2), san.parents(&test_map2)); | ||||||
|  |         println!("First common parent of YOU and SAN: '{}'", parent); | ||||||
|  |         println!("Distance from YOU to {}: {}", parent, you.distance_to(&parent, &test_map2)); | ||||||
|  |         println!("Distance from SAN to {}: {}", parent, san.distance_to(&parent, &test_map2)); | ||||||
|  | 
 | ||||||
|  |         println!("[Test2] Transfers required to go from YOU to SAN: {}", | ||||||
|  |                  you.distance_to(&parent, &test_map2) + san.distance_to(&parent, &test_map2) - 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let map = get_map_from_file("input"); | ||||||
|  |     let mut x: i32 = 0; | ||||||
|  |     for val in map.values() { | ||||||
|  |         x += val.distance_to_com(&map); | ||||||
|  |     } | ||||||
|  |     println!("[Part 1] Total indirect and direct orbits: {}", x); | ||||||
|  | 
 | ||||||
|  |     let you = map.get("YOU").unwrap(); | ||||||
|  |     let you_parents = you.parents(&map); | ||||||
|  |     let san = map.get("SAN").unwrap(); | ||||||
|  |     let san_parents = san.parents(&map); | ||||||
|  |     let common_parent = first_common(you_parents, san_parents); | ||||||
|  |     println!("First common parent of YOU and SAN: '{}'", common_parent); | ||||||
|  |     println!("Distance from YOU to {}: {}", common_parent, you.distance_to(&common_parent, &map)); | ||||||
|  |     println!("Distance from SAN to {}: {}", common_parent, san.distance_to(&common_parent, &map)); | ||||||
|  |     println!("[Part 2] Transfers required to go from YOU to SAN: {}", | ||||||
|  |              you.distance_to(&common_parent, &map) + san.distance_to(&common_parent, &map) - 2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn first_common(a: Vec<String>, b: Vec<String>) -> String { | ||||||
|  |     let mut x: Option<usize> = None; | ||||||
|  |     for v_a in a.iter() { | ||||||
|  |         let mut iter: usize = 0; | ||||||
|  |         for v_b in b.iter() { | ||||||
|  |             if v_a == v_b { | ||||||
|  |                 x = Some(iter); | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             iter += 1; | ||||||
|  |         } | ||||||
|  |         if x.is_some() { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return b[x.unwrap()].clone(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn get_map_from_file(file: &str) -> HashMap<String, Node> { | ||||||
|  |     let contents = std::fs::read_to_string(file) | ||||||
|  |         .expect("Failed to read file 'input'"); | ||||||
|  |     let it = contents.split("\n"); | ||||||
|  |     let mut map: HashMap<String, Node> = HashMap::new(); | ||||||
|  |     for line in it { | ||||||
|  |         let s = String::from(line); | ||||||
|  |         s.trim(); | ||||||
|  |         if s.is_empty() { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         { | ||||||
|  |             let values: Vec<&str> = s.split(")").collect(); | ||||||
|  |             //println!("Line: {}", line);
 | ||||||
|  |             assert_eq!(values.len(), 2); | ||||||
|  |             //assert_eq!(values[0].len(), 3);
 | ||||||
|  |             //assert_eq!(values[1].len(), 3);
 | ||||||
|  |             for v in values { | ||||||
|  |                 if !map.contains_key(v) { | ||||||
|  |                     let n = Node { | ||||||
|  |                         id: v.to_string(), | ||||||
|  |                         parent: None, | ||||||
|  |                         children: Vec::new(), | ||||||
|  |                     }; | ||||||
|  |                     map.insert(v.to_string(), n); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         let values: Vec<&str> = s.split(")").collect(); | ||||||
|  |         { | ||||||
|  |             let mut node = map.get_mut(values[1]).unwrap(); | ||||||
|  |             if !node.parent.is_some() { | ||||||
|  |                 node.parent = Some(values[0].to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         { | ||||||
|  |             let mut node = map.get_mut(values[0]).unwrap(); | ||||||
|  |             if !node.children.contains(&values[1].to_string()) { | ||||||
|  |                 node.children.push(values[1].to_string()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return map; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | struct Node { | ||||||
|  |     parent: Option<String>, | ||||||
|  |     id: String, | ||||||
|  |     children: Vec<String>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Node { | ||||||
|  | 
 | ||||||
|  |     fn distance_to(&self, to: &str, map: &HashMap<String, Node>) -> i32 { | ||||||
|  |         if self.id == to { | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |         let parent = self.parent.as_ref().unwrap().clone(); | ||||||
|  |         return map.get(&parent).unwrap().distance_to(to, map) + 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn distance_to_com(&self, map: &HashMap<String, Node>) -> i32 { | ||||||
|  |         return self.distance_to("COM", map); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn parents(&self, map: &HashMap<String, Node>) -> Vec<String> { | ||||||
|  |         let mut parents: Vec<String> = Vec::new(); | ||||||
|  |         if self.parent.is_some() { | ||||||
|  |             parents.push(self.parent.as_ref().unwrap().clone()); | ||||||
|  |             let parent = map.get(&self.parent.as_ref().unwrap().clone()).unwrap(); | ||||||
|  |             for v in parent.parents(map) { | ||||||
|  |                 parents.push(v); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return parents; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl PartialEq for Node { | ||||||
|  |     fn eq(&self, other: &Self) -> bool { | ||||||
|  |         self.id == other.id | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | COM)B | ||||||
|  | B)C | ||||||
|  | C)D | ||||||
|  | D)E | ||||||
|  | E)F | ||||||
|  | B)G | ||||||
|  | G)H | ||||||
|  | D)I | ||||||
|  | E)J | ||||||
|  | J)K | ||||||
|  | K)L | ||||||
|  | K)YOU | ||||||
|  | I)SAN | ||||||
|  | @ -0,0 +1,30 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day7" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "icc", | ||||||
|  |  "itertools", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "either" | ||||||
|  | version = "1.6.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "icc" | ||||||
|  | version = "1.0.0" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "itertools" | ||||||
|  | version = "0.10.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" | ||||||
|  | dependencies = [ | ||||||
|  |  "either", | ||||||
|  | ] | ||||||
|  | @ -0,0 +1,10 @@ | ||||||
|  | [package] | ||||||
|  | name = "day7" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | icc = { path = "../icc", version = "1.0.0"} | ||||||
|  | itertools = "0.10.3" | ||||||
|  | @ -0,0 +1,132 @@ | ||||||
|  | use std::collections::VecDeque; | ||||||
|  | use itertools::Itertools; | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let program = vec![3,8,1001,8,10,8,105,1,0,0,21,38,63,88,97,118,199,280,361,442,99999,3,9,1002,9,3,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,101,3,9,9,102,5,9,9,101,3,9,9,1002,9,3,9,101,3,9,9,4,9,99,3,9,1002,9,2,9,1001,9,3,9,102,3,9,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,102,2,9,9,4,9,99,3,9,102,4,9,9,101,5,9,9,102,2,9,9,101,5,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99]; | ||||||
|  | 
 | ||||||
|  |     let mut max_storage = 0; | ||||||
|  |     let mut max_settings: Vec<i32> = Vec::new(); | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let settings = vec![0, 1, 2, 3, 4]; | ||||||
|  |         // Cheese. | ||||||
|  |         for permutation in settings.into_iter().permutations(5) { | ||||||
|  |             //println!("{:?}", permutation); | ||||||
|  |             let storage = run_amplifiers(&program, permutation.clone()); | ||||||
|  |             if storage > max_storage { | ||||||
|  |                 max_storage = storage; | ||||||
|  |                 max_settings = permutation.clone(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         println!("[Part 1] Settings {:?} produced a value of {}", max_settings, max_storage); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let settings = vec![5, 6, 7, 8, 9]; | ||||||
|  |         for permutation in settings.into_iter().permutations(5) { | ||||||
|  |             let storage = run_feedback_amplifiers(&program, permutation.clone()); | ||||||
|  |             if storage > max_storage { | ||||||
|  |                 max_storage = storage; | ||||||
|  |                 max_settings = permutation.clone(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         println!("[Part 2] Settings {:?} produced a value of {}", max_settings, max_storage); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn run_amplifiers(program: &Vec<i32>, settings: Vec<i32>) -> i32 { | ||||||
|  |     let mut storage: i32 = 0; | ||||||
|  |     for setting in settings { | ||||||
|  |         let mut input = VecDeque::from([setting, storage]); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         icc::simulate(&mut program.clone(), &mut input, &mut output, 0); | ||||||
|  |         storage = output[0]; | ||||||
|  |     } | ||||||
|  |     return storage; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn run_feedback_amplifiers(program: &Vec<i32>, settings: Vec<i32>) -> i32 { | ||||||
|  |     let amplifiers = [ | ||||||
|  |         // program, input signal, entrypoint, setting | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |     ]; | ||||||
|  |     let mut iter: i32 = 0; | ||||||
|  |     loop { | ||||||
|  |         for (index, setting) in settings.iter().enumerate() { | ||||||
|  |             match amplifiers[index].3 { | ||||||
|  |                 icc::Status::Finished => { | ||||||
|  |                     if index == 4 { | ||||||
|  |                         // the output of amplifier 4 is stored on the input of amplifier 0 | ||||||
|  |                         return *amplifiers[0].1; | ||||||
|  |                     } | ||||||
|  |                     continue; | ||||||
|  |                 }, | ||||||
|  |                 _ => {} | ||||||
|  |             } | ||||||
|  |             println!("[Iter {}] Running amplifier {} from instruction {}", iter, index, *amplifiers[index].2); | ||||||
|  |             let mut input = if iter == 0 { | ||||||
|  |                 VecDeque::from([*setting, *amplifiers[index].1]) | ||||||
|  |             } else { | ||||||
|  |                 VecDeque::from([*amplifiers[index].1]) | ||||||
|  |             }; | ||||||
|  |             let mut output: Vec<i32> = Vec::new(); | ||||||
|  |             let result = icc::simulate(amplifiers[index].0, &mut input, &mut output, *amplifiers[index].2); | ||||||
|  |             match result.status { | ||||||
|  |                 icc::Status::WaitingForInput => { | ||||||
|  |                     println!("[Iter {}] Amplifier {} is waiting for input", iter, index); | ||||||
|  |                 }, | ||||||
|  |                 _ => {}, | ||||||
|  |             } | ||||||
|  |             let amp_index = (index+1) % settings.len(); | ||||||
|  |             *amplifiers[amp_index].1 = output[0]; | ||||||
|  |             println!("[Iter {}] Amplifier {}->{}: {}", iter, index, amp_index, output[0]); | ||||||
|  |             *amplifiers[index].2 = result.instruction; | ||||||
|  |             *amplifiers[index].3 = result.status; | ||||||
|  |         } | ||||||
|  |         iter += 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_1() { | ||||||
|  |         let program = vec![3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]; | ||||||
|  |         let settings = vec![4, 3, 2, 1, 0]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 43210); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_2() { | ||||||
|  |         let program = vec![3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0]; | ||||||
|  |         let settings = vec![0,1,2,3,4]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 54321); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_3() { | ||||||
|  |         let program = vec![3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0]; | ||||||
|  |         let settings = vec![1,0,4,3,2]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 65210); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example_1() { | ||||||
|  |         let program = vec![3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]; | ||||||
|  |         let settings = vec![9,8,7,6,5]; | ||||||
|  |         assert_eq!(run_feedback_amplifiers(&program, settings), 139629729); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example_2() { | ||||||
|  |         let program = vec![3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10]; | ||||||
|  |         let settings = vec![9,7,8,5,6]; | ||||||
|  |         assert_eq!(run_feedback_amplifiers(&program, settings), 18216); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | kienan@monolith.244424:1652264161 | ||||||
|  | @ -0,0 +1,132 @@ | ||||||
|  | use std::collections::VecDeque; | ||||||
|  | use itertools::Itertools; | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let program = vec![3,8,1001,8,10,8,105,1,0,0,21,38,63,88,97,118,199,280,361,442,99999,3,9,1002,9,3,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,101,3,9,9,102,5,9,9,101,3,9,9,1002,9,3,9,101,3,9,9,4,9,99,3,9,1002,9,2,9,1001,9,3,9,102,3,9,9,101,2,9,9,1002,9,4,9,4,9,99,3,9,102,2,9,9,4,9,99,3,9,102,4,9,9,101,5,9,9,102,2,9,9,101,5,9,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,99,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,1,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,102,2,9,9,4,9,99,3,9,102,2,9,9,4,9,3,9,101,1,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1002,9,2,9,4,9,3,9,102,2,9,9,4,9,3,9,1002,9,2,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,1,9,9,4,9,99,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,101,1,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,3,9,101,2,9,9,4,9,3,9,102,2,9,9,4,9,3,9,1001,9,1,9,4,9,3,9,1001,9,2,9,4,9,99]; | ||||||
|  | 
 | ||||||
|  |     let mut max_storage = 0; | ||||||
|  |     let mut max_settings: Vec<i32> = Vec::new(); | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let settings = vec![0, 1, 2, 3, 4]; | ||||||
|  |         // Cheese.
 | ||||||
|  |         for permutation in settings.into_iter().permutations(5) { | ||||||
|  |             //println!("{:?}", permutation);
 | ||||||
|  |             let storage = run_amplifiers(&program, permutation.clone()); | ||||||
|  |             if storage > max_storage { | ||||||
|  |                 max_storage = storage; | ||||||
|  |                 max_settings = permutation.clone(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         println!("[Part 1] Settings {:?} produced a value of {}", max_settings, max_storage); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let settings = vec![5, 6, 7, 8, 9]; | ||||||
|  |         for permutation in settings.into_iter().permutations(5) { | ||||||
|  |             let storage = run_feedback_amplifiers(&program, permutation.clone()); | ||||||
|  |             if storage > max_storage { | ||||||
|  |                 max_storage = storage; | ||||||
|  |                 max_settings = permutation.clone(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         println!("[Part 2] Settings {:?} produced a value of {}", max_settings, max_storage); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn run_amplifiers(program: &Vec<i32>, settings: Vec<i32>) -> i32 { | ||||||
|  |     let mut storage: i32 = 0; | ||||||
|  |     for setting in settings { | ||||||
|  |         let mut input = VecDeque::from([setting, storage]); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         icc::simulate(&mut program.clone(), &mut input, &mut output, 0); | ||||||
|  |         storage = output[0]; | ||||||
|  |     } | ||||||
|  |     return storage; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn run_feedback_amplifiers(program: &Vec<i32>, settings: Vec<i32>) -> i32 { | ||||||
|  |     let amplifiers = [ | ||||||
|  |         // program, input signal, entrypoint, setting
 | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |         (&mut program.clone(), &mut 0, &mut 0usize, &mut icc::Status::Running), | ||||||
|  |     ]; | ||||||
|  |     let mut iter: i32 = 0; | ||||||
|  |     loop { | ||||||
|  |         for (index, setting) in settings.iter().enumerate() { | ||||||
|  |             match amplifiers[index].3 { | ||||||
|  |                 icc::Status::Finished => { | ||||||
|  |                     if index == 4 { | ||||||
|  |                         // the output of amplifier 4 is stored on the input of amplifier 0
 | ||||||
|  |                         return *amplifiers[0].1; | ||||||
|  |                     } | ||||||
|  |                     continue; | ||||||
|  |                 }, | ||||||
|  |                 _ => {} | ||||||
|  |             } | ||||||
|  |             println!("[Iter {}] Running amplifier {} from instruction {}", iter, index, *amplifiers[index].2); | ||||||
|  |             let mut input = if iter == 0 { | ||||||
|  |                 VecDeque::from([*setting, *amplifiers[index].1]) | ||||||
|  |             } else { | ||||||
|  |                 VecDeque::from([*amplifiers[index].1]) | ||||||
|  |             }; | ||||||
|  |             let mut output: Vec<i32> = Vec::new(); | ||||||
|  |             let result = icc::simulate(amplifiers[index].0, &mut input, &mut output, *amplifiers[index].2); | ||||||
|  |             match result.status { | ||||||
|  |                 icc::Status::WaitingForInput => { | ||||||
|  |                     println!("[Iter {}] Amplifier {} is waiting for input", iter, index); | ||||||
|  |                 }, | ||||||
|  |                 _ => {}, | ||||||
|  |             } | ||||||
|  |             let amp_index = (index+1) % settings.len(); | ||||||
|  |             *amplifiers[amp_index].1 = output[0]; | ||||||
|  |             println!("[Iter {}] Amplifier {}->{}: {}", iter, index, amp_index, output[0]); | ||||||
|  |             *amplifiers[index].2 = result.instruction; | ||||||
|  |             *amplifiers[index].3 = result.status; | ||||||
|  |         } | ||||||
|  |         iter += 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_1() { | ||||||
|  |         let program = vec![3,15,3,16,1002,16,10,16,1,16,15,15,4,15,99,0,0]; | ||||||
|  |         let settings = vec![4, 3, 2, 1, 0]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 43210); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_2() { | ||||||
|  |         let program = vec![3,23,3,24,1002,24,10,24,1002,23,-1,23,101,5,23,23,1,24,23,23,4,23,99,0,0]; | ||||||
|  |         let settings = vec![0,1,2,3,4]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 54321); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn example_3() { | ||||||
|  |         let program = vec![3,31,3,32,1002,32,10,32,1001,31,-2,31,1007,31,0,33,1002,33,7,33,1,33,31,31,1,32,31,31,4,31,99,0,0,0]; | ||||||
|  |         let settings = vec![1,0,4,3,2]; | ||||||
|  |         assert_eq!(run_amplifiers(&program, settings), 65210); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example_1() { | ||||||
|  |         let program = vec![3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]; | ||||||
|  |         let settings = vec![9,8,7,6,5]; | ||||||
|  |         assert_eq!(run_feedback_amplifiers(&program, settings), 139629729); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn part2_example_2() { | ||||||
|  |         let program = vec![3,52,1001,52,-5,52,3,53,1,52,56,54,1007,54,5,55,1005,55,26,1001,54,-5,54,1105,1,12,1,53,54,53,1008,54,0,55,1001,55,1,55,2,53,55,53,4,53,1001,56,-1,56,1005,56,6,99,0,0,0,0,10]; | ||||||
|  |         let settings = vec![9,7,8,5,6]; | ||||||
|  |         assert_eq!(run_feedback_amplifiers(&program, settings), 18216); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day8" | ||||||
|  | version = "0.1.0" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "day8" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -0,0 +1,122 @@ | ||||||
|  | struct Image { | ||||||
|  |     width: usize, | ||||||
|  |     height: usize, | ||||||
|  |     layers: Vec<Vec<u32>>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Image { | ||||||
|  |     fn from_str(width: usize, height: usize, data: &str) -> Image { | ||||||
|  |         assert_eq!(data.len() % (width * height), 0); | ||||||
|  |         let mut image = Image { | ||||||
|  |             width: width, | ||||||
|  |             height: height, | ||||||
|  |             layers: Vec::new(), | ||||||
|  |         }; | ||||||
|  |         let mut layer: usize = 0; | ||||||
|  |         image.layers.push(Vec::new()); | ||||||
|  |         let mut index: usize = 0; | ||||||
|  |         for c in data.chars() { | ||||||
|  |             if index >= (width*height) { | ||||||
|  |                 layer += 1; | ||||||
|  |                 image.layers.push(Vec::new()); | ||||||
|  |                 index = 0; | ||||||
|  |             } | ||||||
|  |             image.layers[layer].push(c.to_digit(10).expect("Could not convert character to digit")); | ||||||
|  |             index += 1; | ||||||
|  |         } | ||||||
|  |         return image; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn layer_n_digits(&self, layer_index: usize, value: u32) -> usize { | ||||||
|  |         let mut count: usize = 0; | ||||||
|  |         for v in self.layers[layer_index].iter() { | ||||||
|  |             if *v == value { | ||||||
|  |                 count += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return count; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn layer_merge(&self) -> Vec<u32> { | ||||||
|  |         let mut result: Vec<u32> = Vec::new(); | ||||||
|  |         result.resize(self.width * self.height, 2); | ||||||
|  |         for pixel_index in 0..(self.width*self.height) { | ||||||
|  |             for layer_index in 0..self.layers.len() { | ||||||
|  |                 // 2 is transparent
 | ||||||
|  |                 let value = self.layers[layer_index][pixel_index]; | ||||||
|  |                 if value != 2 { | ||||||
|  |                     result[pixel_index] = value; | ||||||
|  |                     break; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return result; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let data = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read 'input'"); | ||||||
|  |     let image = Image::from_str(25, 6, &data); | ||||||
|  |     println!("Image contains {} layers", image.layers.len()); | ||||||
|  |     let mut layer_fewest_zeroes: usize = 0; | ||||||
|  |     let mut least_zeroes: usize = 200; | ||||||
|  |     for index in 0..image.layers.len() { | ||||||
|  |         let n_zeroes = image.layer_n_digits(index, 0); | ||||||
|  |         if n_zeroes < least_zeroes { | ||||||
|  |             layer_fewest_zeroes = index; | ||||||
|  |             least_zeroes = n_zeroes; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     println!("Layer {} has {} zeroes", layer_fewest_zeroes, least_zeroes); | ||||||
|  |     println!("[Part 1] {}", image.layer_n_digits(layer_fewest_zeroes, 1) * image.layer_n_digits(layer_fewest_zeroes, 2)); | ||||||
|  | 
 | ||||||
|  |     let merged = image.layer_merge(); | ||||||
|  |     let mut n: u32 = 0; | ||||||
|  |     for i in merged.iter() { | ||||||
|  |         let c = if *i == 0 { | ||||||
|  |             '⬛' | ||||||
|  |         } else if *i == 1 { | ||||||
|  |             '⬜' | ||||||
|  |         } | ||||||
|  |         else if *i == 2 { | ||||||
|  |             ' ' | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             '?' | ||||||
|  |         }; | ||||||
|  |         print!("{}", c); | ||||||
|  |         n += 1; | ||||||
|  |         if n % 25 == 0 { | ||||||
|  |             print!("\n"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod test { | ||||||
|  | 
 | ||||||
|  |     use super::*; | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn create_image() { | ||||||
|  |         let data = "123456789012"; | ||||||
|  |         let image = Image::from_str(3, 2, data); | ||||||
|  |         assert_eq!(image.layers.len(), 2); | ||||||
|  |         let layer_0 = vec![1, 2, 3, 4, 5, 6]; | ||||||
|  |         let layer_1 = vec![7, 8, 9, 0, 1, 2]; | ||||||
|  |         assert_eq!(image.layers[0], layer_0); | ||||||
|  |         assert_eq!(image.layers[1], layer_1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn layer_merge() { | ||||||
|  |         let data = "0222112222120000"; | ||||||
|  |         let image = Image::from_str(2, 2, data); | ||||||
|  |         let merged = image.layer_merge(); | ||||||
|  |         assert_eq!(merged[0], 0); | ||||||
|  |         assert_eq!(merged[1], 1); | ||||||
|  |         assert_eq!(merged[2], 1); | ||||||
|  |         assert_eq!(merged[3], 0); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "day9" | ||||||
|  | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "icc", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "icc" | ||||||
|  | version = "1.1.2" | ||||||
|  | @ -0,0 +1,9 @@ | ||||||
|  | [package] | ||||||
|  | name = "day9" | ||||||
|  | version = "0.1.0" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | icc = { path = "../icc", version = "1.1.1"} | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | 1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,432,1027,1101,439,0,1026,1101,0,36,1010,1101,0,34,1018,1102,278,1,1029,1101,0,24,1002,1102,1,20,1016,1102,1,31,1011,1102,319,1,1024,1102,21,1,1012,1102,1,763,1022,1102,1,25,1007,1101,0,287,1028,1102,32,1,1008,1101,0,22,1013,1102,38,1,1001,1101,0,314,1025,1102,35,1,1009,1102,1,23,1015,1102,39,1,1019,1102,27,1,1000,1102,1,37,1003,1102,1,28,1017,1101,0,0,1020,1101,0,29,1004,1102,1,30,1006,1102,1,756,1023,1102,1,33,1005,1101,0,1,1021,1102,26,1,1014,109,13,2108,28,-7,63,1005,63,201,1001,64,1,64,1105,1,203,4,187,1002,64,2,64,109,8,21107,40,41,-3,1005,1018,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,-3,1206,2,239,4,231,1105,1,243,1001,64,1,64,1002,64,2,64,109,-21,1201,6,0,63,1008,63,35,63,1005,63,267,1001,64,1,64,1105,1,269,4,249,1002,64,2,64,109,35,2106,0,-4,4,275,1001,64,1,64,1105,1,287,1002,64,2,64,109,-11,1205,-1,303,1001,64,1,64,1105,1,305,4,293,1002,64,2,64,109,8,2105,1,-5,4,311,1106,0,323,1001,64,1,64,1002,64,2,64,109,-7,21108,41,38,-6,1005,1016,339,1106,0,345,4,329,1001,64,1,64,1002,64,2,64,109,2,21102,42,1,-8,1008,1016,45,63,1005,63,369,1001,64,1,64,1105,1,371,4,351,1002,64,2,64,109,-14,21101,43,0,1,1008,1011,43,63,1005,63,397,4,377,1001,64,1,64,1106,0,397,1002,64,2,64,109,-8,21101,44,0,8,1008,1010,47,63,1005,63,417,1105,1,423,4,403,1001,64,1,64,1002,64,2,64,109,25,2106,0,0,1001,64,1,64,1105,1,441,4,429,1002,64,2,64,109,-20,2107,37,-6,63,1005,63,463,4,447,1001,64,1,64,1106,0,463,1002,64,2,64,109,8,2108,25,-8,63,1005,63,485,4,469,1001,64,1,64,1106,0,485,1002,64,2,64,109,-1,21107,45,44,-1,1005,1013,505,1001,64,1,64,1106,0,507,4,491,1002,64,2,64,109,-11,1207,-1,25,63,1005,63,529,4,513,1001,64,1,64,1106,0,529,1002,64,2,64,109,23,1206,-5,545,1001,64,1,64,1106,0,547,4,535,1002,64,2,64,109,-31,2102,1,5,63,1008,63,27,63,1005,63,569,4,553,1106,0,573,1001,64,1,64,1002,64,2,64,109,27,21102,46,1,-9,1008,1013,46,63,1005,63,595,4,579,1105,1,599,1001,64,1,64,1002,64,2,64,109,-26,2101,0,6,63,1008,63,24,63,1005,63,625,4,605,1001,64,1,64,1106,0,625,1002,64,2,64,109,5,1208,0,37,63,1005,63,645,1001,64,1,64,1105,1,647,4,631,1002,64,2,64,109,7,2102,1,-3,63,1008,63,31,63,1005,63,671,1001,64,1,64,1105,1,673,4,653,1002,64,2,64,109,2,1202,-5,1,63,1008,63,33,63,1005,63,699,4,679,1001,64,1,64,1105,1,699,1002,64,2,64,109,-4,2101,0,-3,63,1008,63,35,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,-5,1207,4,32,63,1005,63,741,1106,0,747,4,731,1001,64,1,64,1002,64,2,64,109,29,2105,1,-7,1001,64,1,64,1106,0,765,4,753,1002,64,2,64,109,-26,2107,36,5,63,1005,63,781,1105,1,787,4,771,1001,64,1,64,1002,64,2,64,109,10,1201,-6,0,63,1008,63,32,63,1005,63,809,4,793,1106,0,813,1001,64,1,64,1002,64,2,64,109,3,21108,47,47,-5,1005,1012,835,4,819,1001,64,1,64,1106,0,835,1002,64,2,64,109,-24,1202,9,1,63,1008,63,25,63,1005,63,859,1001,64,1,64,1106,0,861,4,841,1002,64,2,64,109,19,1205,9,875,4,867,1106,0,879,1001,64,1,64,1002,64,2,64,109,-3,1208,-1,32,63,1005,63,897,4,885,1106,0,901,1001,64,1,64,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,60043,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0 | ||||||
|  | @ -0,0 +1,26 @@ | ||||||
|  | use std::str::FromStr; | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  |     let data = std::fs::read_to_string("input") | ||||||
|  |         .expect("Failed to read 'input'"); | ||||||
|  |     let mut program: Vec<i64> = Vec::new(); | ||||||
|  |     for v in data.split(",") { | ||||||
|  |         program.push(i64::from_str(v).unwrap()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     { | ||||||
|  |         let mut c = icc::Computer::initialize(program.clone(), vec![1]); | ||||||
|  |         c.run(); | ||||||
|  |         if c.output.len() > 1 { | ||||||
|  |             println!("Some op-codes report failures"); | ||||||
|  |             println!("Test output: {:?}", c.output); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         println!("[Part 1] {}", c.output[0]); | ||||||
|  |     } | ||||||
|  |     { | ||||||
|  |         let mut c = icc::Computer::initialize(program.clone(), vec![2]); | ||||||
|  |         c.run(); | ||||||
|  |         println!("[Part 2] {}", c.output[0]); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | @ -0,0 +1,7 @@ | ||||||
|  | # This file is automatically @generated by Cargo. | ||||||
|  | # It is not intended for manual editing. | ||||||
|  | version = 3 | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "icc" | ||||||
|  | version = "1.1.2" | ||||||
|  | @ -0,0 +1,8 @@ | ||||||
|  | [package] | ||||||
|  | name = "icc" | ||||||
|  | version = "1.1.2" | ||||||
|  | edition = "2021" | ||||||
|  | 
 | ||||||
|  | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
|  | 
 | ||||||
|  | [dependencies] | ||||||
|  | @ -0,0 +1,500 @@ | ||||||
|  | use std::collections::VecDeque; | ||||||
|  | use std::collections::HashMap; | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | #[derive(PartialEq)] | ||||||
|  | #[derive(Copy, Clone)] | ||||||
|  | pub enum Status { | ||||||
|  |     Running, | ||||||
|  |     Finished, | ||||||
|  |     WaitingForInput, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct Result { | ||||||
|  |     pub status: Status, | ||||||
|  |     pub instruction: usize, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub struct Computer { | ||||||
|  |     memory: HashMap<usize, i64>, | ||||||
|  |     position: usize, | ||||||
|  |     relative_base: i64, | ||||||
|  |     input: VecDeque<i64>, | ||||||
|  |     pub output: Vec<i64>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | #[derive(Copy, Clone)] | ||||||
|  | enum Operation { | ||||||
|  |     Add, | ||||||
|  |     Mul, | ||||||
|  |     Input, | ||||||
|  |     Output, | ||||||
|  |     JumpIfTrue, | ||||||
|  |     JumpIfFalse, | ||||||
|  |     LessThan, | ||||||
|  |     Equals, | ||||||
|  |     AdjustRelativeBase, | ||||||
|  |     End, // 99
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[derive(Debug)] | ||||||
|  | #[derive(Copy, Clone)] | ||||||
|  | enum ParameterMode { | ||||||
|  |     Position,  // 0
 | ||||||
|  |     Immediate, // 1
 | ||||||
|  |     Relative,  // 2
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl ParameterMode { | ||||||
|  |     pub fn from_int(i: i64) -> ParameterMode { | ||||||
|  |         if i == 0 { | ||||||
|  |             ParameterMode::Position | ||||||
|  |         } | ||||||
|  |         else if i == 1 { | ||||||
|  |             ParameterMode::Immediate | ||||||
|  |         } | ||||||
|  |         else if i == 2 { | ||||||
|  |             ParameterMode::Relative | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             panic!("Unknown parameter mode integer value: {}", i); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl Computer { | ||||||
|  |     pub fn initialize(program: Vec<i64>, input: Vec<i64>) -> Self { | ||||||
|  |         let mut computer = Computer { | ||||||
|  |             memory: HashMap::new(), | ||||||
|  |             position: 0, | ||||||
|  |             relative_base: 0, | ||||||
|  |             input: VecDeque::from(input), | ||||||
|  |             output: Vec::new(), | ||||||
|  |         }; | ||||||
|  |         for i in 0..program.len() { | ||||||
|  |             computer.mem_put(i, program[i]); | ||||||
|  |         } | ||||||
|  |         return computer; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn mem_put(&mut self, address: usize, value: i64) { | ||||||
|  |         self.memory.insert(address, value); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn mem_get(&mut self, address: usize) -> i64 { | ||||||
|  |         let value = self.memory.get(&address); | ||||||
|  |         if value.is_none() { | ||||||
|  |             self.mem_put(address, 0); | ||||||
|  |             return 0; | ||||||
|  |         } | ||||||
|  |         return *value.unwrap(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     pub fn run(&mut self) -> Status { | ||||||
|  |         loop { | ||||||
|  |             let (op, p1_mode, p2_mode, p3_mode) = Self::decode_instruction( | ||||||
|  |                 self.mem_get(self.position) | ||||||
|  |             ); | ||||||
|  |             match op { | ||||||
|  |                 Operation::Add => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     let dest = self.absolute_address(self.position + 3, p3_mode); | ||||||
|  |                     self.mem_put(dest, d1 + d2); | ||||||
|  |                     self.position += 4; | ||||||
|  |                 }, | ||||||
|  |                 Operation::Mul => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     let dest = self.absolute_address(self.position + 3, p3_mode); | ||||||
|  |                     self.mem_put(dest, d1 * d2); | ||||||
|  |                     self.position += 4; | ||||||
|  |                 }, | ||||||
|  |                 Operation::Input => { | ||||||
|  |                     if self.input.len() == 0 { | ||||||
|  |                         return Status::WaitingForInput; | ||||||
|  |                     } | ||||||
|  |                     let dest = self.absolute_address(self.position + 1, p1_mode); | ||||||
|  |                     let input = self.input.pop_front().expect("Input queue empty... weird"); | ||||||
|  |                     self.mem_put(dest, input); | ||||||
|  |                     println!("Input: {}", input); | ||||||
|  |                     self.position += 2; | ||||||
|  |                 }, | ||||||
|  |                 Operation::Output => { | ||||||
|  |                     let value = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     println!("Output: {}", value); | ||||||
|  |                     self.output.push(value); | ||||||
|  |                     self.position += 2; | ||||||
|  |                 }, | ||||||
|  |                 Operation::JumpIfTrue => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     if d1 != 0 { | ||||||
|  |                         self.position = d2 as usize; | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         self.position += 3; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 Operation::JumpIfFalse => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     if d1 == 0 { | ||||||
|  |                         self.position = d2 as usize; | ||||||
|  |                     } | ||||||
|  |                     else { | ||||||
|  |                         self.position += 3; | ||||||
|  |                     } | ||||||
|  |                 }, | ||||||
|  |                 Operation::LessThan => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     let dest = self.absolute_address(self.position + 3, p3_mode); | ||||||
|  |                     self.mem_put(dest, if d1 < d2 { 1 } else { 0 }); | ||||||
|  |                     self.position += 4; | ||||||
|  |                 }, | ||||||
|  |                 Operation::Equals => { | ||||||
|  |                     let d1 = self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     let d2 = self.fetch(self.position + 2, p2_mode); | ||||||
|  |                     let dest = self.absolute_address(self.position + 3, p3_mode); | ||||||
|  |                     self.mem_put(dest, if d1 == d2 { 1 } else { 0 }); | ||||||
|  |                     self.position += 4; | ||||||
|  |                 }, | ||||||
|  |                 Operation::AdjustRelativeBase => { | ||||||
|  |                     self.relative_base += self.fetch(self.position + 1, p1_mode); | ||||||
|  |                     //println!("[RB: {}]", self.relative_base);
 | ||||||
|  |                     self.position += 2; | ||||||
|  |                 }, | ||||||
|  |                 Operation::End => { | ||||||
|  |                     break; | ||||||
|  |                 }, | ||||||
|  |                 other => { | ||||||
|  |                     panic!("'{:?}' not implemented", other); | ||||||
|  |                 }, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|  |         return Status::Finished; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn fetch(&mut self, pos: usize, mode: ParameterMode) -> i64 { | ||||||
|  |         let addr = self.absolute_address(pos, mode); | ||||||
|  |         return self.mem_get(addr); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn absolute_address(&mut self, pos: usize, mode: ParameterMode) -> usize { | ||||||
|  |         match mode { | ||||||
|  |             ParameterMode::Position => { | ||||||
|  |                 self.mem_get( | ||||||
|  |                     pos | ||||||
|  |                 ) as usize | ||||||
|  |             }, | ||||||
|  |             ParameterMode::Immediate => { | ||||||
|  |                 pos | ||||||
|  |             }, | ||||||
|  |             ParameterMode::Relative => { | ||||||
|  |                 let p = self.mem_get(pos) as i64 + self.relative_base; | ||||||
|  |                 if p < 0 { | ||||||
|  |                     panic!("Attempting to resolve illegale address: {}", p); | ||||||
|  |                 } | ||||||
|  |                 return p as usize; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn decode_instruction(code: i64) -> (Operation, ParameterMode, ParameterMode, ParameterMode) { | ||||||
|  |         // Opcodes are ABCDE, where the op is DE
 | ||||||
|  |         // the modes for params 1, 2, and 3 as C, B, A
 | ||||||
|  |         // respectively.
 | ||||||
|  |         let mut c = code; | ||||||
|  |         let op_int = code % 100; | ||||||
|  |         let op = if op_int == 1 { | ||||||
|  |             Operation::Add | ||||||
|  |         } else if op_int == 2 { | ||||||
|  |             Operation::Mul | ||||||
|  |         } else if op_int == 3 { | ||||||
|  |             Operation::Input | ||||||
|  |         } else if op_int == 4 { | ||||||
|  |             Operation::Output | ||||||
|  |         } else if op_int == 5 { | ||||||
|  |             Operation::JumpIfTrue | ||||||
|  |         } else if op_int == 6 { | ||||||
|  |             Operation::JumpIfFalse | ||||||
|  |         } else if op_int == 7 { | ||||||
|  |             Operation::LessThan | ||||||
|  |         } else if op_int == 8 { | ||||||
|  |             Operation::Equals | ||||||
|  |         } else if op_int == 9 { | ||||||
|  |             Operation::AdjustRelativeBase | ||||||
|  |         }else if op_int == 99 { | ||||||
|  |             Operation::End | ||||||
|  |         } else { | ||||||
|  |             panic!("Unknown opcode: {}", op_int); | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         let param_3_mode_int = c / 10000; | ||||||
|  |         c -= param_3_mode_int * 10000; | ||||||
|  |         let param_2_mode_int = c / 1000; | ||||||
|  |         c -= param_2_mode_int * 1000; | ||||||
|  |         let param_1_mode_int = c / 100; | ||||||
|  |         return ( | ||||||
|  |             op, | ||||||
|  |             ParameterMode::from_int(param_1_mode_int), | ||||||
|  |             ParameterMode::from_int(param_2_mode_int), | ||||||
|  |             ParameterMode::from_int(param_3_mode_int), | ||||||
|  |         ); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn simulate(v: &mut Vec<i32>, input: &mut VecDeque<i32>, output: &mut Vec<i32>, start: usize) -> Result { | ||||||
|  |     let mut program: Vec<i64> = Vec::new(); | ||||||
|  |     for i in 0..v.len() { | ||||||
|  |         program.push(i64::from(v[i])); | ||||||
|  |     } | ||||||
|  |     let mut ip: VecDeque<i64> = VecDeque::new(); | ||||||
|  |     for i in 0..input.len() { | ||||||
|  |         ip.push_front(i64::from(input[i])); | ||||||
|  |     } | ||||||
|  |     let mut computer = Computer::initialize(program, vec![]); | ||||||
|  |     computer.input = ip; | ||||||
|  |     computer.position = start; | ||||||
|  |     let r = computer.run(); | ||||||
|  |     for i in 0..computer.output.len() { | ||||||
|  |         if computer.output[i] <= i64::from(i32::MAX) && computer.output[i] >= i64::from(i32::MIN) { | ||||||
|  |             output.push(computer.output[i] as i32); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             panic!("Output value '{}' out of range for legacy i32 int-code computer", computer.output[i]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     for i in 0..v.len() { | ||||||
|  |         v[i] = computer.mem_get(i) as i32; | ||||||
|  |     } | ||||||
|  |     return Result { | ||||||
|  |         status: r, | ||||||
|  |         instruction: computer.position, | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |     #[test] | ||||||
|  |     fn test_op_1() { | ||||||
|  |         let mut program = vec![1, 0, 0, 0, 99]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[0], 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_op_2() { | ||||||
|  |         let mut program = vec![2, 3, 0, 3, 99]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[3], 6); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_case_3() { | ||||||
|  |         let mut program = vec![2,4,4,5,99,0]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[program.len() - 1], 9801); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn test_case_4() { | ||||||
|  |         let mut program = vec![1,1,1,4,99,5,6,0,99]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[0], 30); | ||||||
|  |         assert_eq!(program[4], 2); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn immediate_mode_multiply() { | ||||||
|  |         let mut program = vec![1002,4,3,4,33]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[4], 99); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn negative_integers() { | ||||||
|  |         let mut program = vec![1101,100,-1,4,0]; | ||||||
|  |         let mut input: VecDeque<i32> = VecDeque::new(); | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         simulate(&mut program, &mut input, &mut output, 0); | ||||||
|  |         assert_eq!(program[4], 99); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn position_mode_input_equal_to_8() { | ||||||
|  |         let mut program = vec![3,9,8,9,10,9,4,9,99,-1,8]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([7]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn position_mode_input_less_than_8() { | ||||||
|  |         let mut program = vec![3,9,7,9,10,9,4,9,99,-1,8]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([7]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn immediate_mode_input_equal_to_8() { | ||||||
|  |         let mut program = vec![3,3,1108,-1,8,3,4,3,99]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([7]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn immediate_mode_input_less_than_8() { | ||||||
|  |         let mut program = vec![3,3,1107,-1,8,3,4,3,99]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([7]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn position_mode_input_is_non_zero() { | ||||||
|  |         let mut program = vec![3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([0]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn immediate_mode_input_is_non_zero() { | ||||||
|  |         let mut program = vec![3,3,1105,-1,9,1101,0,0,12,4,12,99,1]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([9]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([0]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 0); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn multi_jump() { | ||||||
|  |         let mut program = vec![3,21,1008,21,8,20,1005,20,22,107,8,21,20,1006,20,31,1106,0,36,98,0,0,1002,21,125,20,4,20,1105,1,46,104,999,1105,1,46,1101,1000,1,20,4,20,1105,1,46,98,99]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let backup = program.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([7]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 999); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([8]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1000); | ||||||
|  |         output.clear(); | ||||||
|  |         program = backup.clone(); | ||||||
|  |         simulate(&mut program, &mut VecDeque::from([9]), &mut output, 0); | ||||||
|  |         assert_eq!(output[0], 1001); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn blocks_on_input() { | ||||||
|  |         let mut program = vec![3,26,1001,26,-4,26,3,27,1002,27,2,27,1,27,26,27,4,27,1001,28,-1,28,1005,28,6,99,0,0,5]; | ||||||
|  |         let mut output: Vec<i32> = Vec::new(); | ||||||
|  |         let result = simulate(&mut program, &mut VecDeque::from([9, 0]), &mut output, 0); | ||||||
|  |         assert_eq!(result.status, Status::WaitingForInput); | ||||||
|  |         assert_eq!(result.instruction, 6); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn relative_base_adjust() { | ||||||
|  |         let mut c = Computer::initialize(vec![109, 1, 99], vec![]); | ||||||
|  |         c.run(); | ||||||
|  |         assert_eq!(c.relative_base, 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     #[should_panic] | ||||||
|  |     fn negative_memory_access() { | ||||||
|  |         let mut c = Computer::initialize(vec![109, -5000, 204, 0, 99], vec![]); | ||||||
|  |         c.run(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn relative_example_1() { | ||||||
|  |         // The program produces an output of itself
 | ||||||
|  |         let program = vec![109,1,204,-1,1001,100,1,100,1008,100,16,101,1006,101,0,99]; | ||||||
|  |         let mut c = Computer::initialize(program.clone(), vec![]); | ||||||
|  |         c.run(); | ||||||
|  |         for i in 0..program.len() { | ||||||
|  |             assert_eq!(program[i], c.output[i]); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn relative_example_2() { | ||||||
|  |         // Outputs a 16 digit numbers
 | ||||||
|  |         let program = vec![1102,34915192,34915192,7,4,7,99,0]; | ||||||
|  |         let mut c = Computer::initialize(program, vec![]); | ||||||
|  |         c.run(); | ||||||
|  |         assert_eq!(c.output[0].to_string().len(), 16); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn relative_example_3() { | ||||||
|  |         // Outputs 1125899906842624
 | ||||||
|  |         let program = vec![104,1125899906842624,99]; | ||||||
|  |         let mut c = Computer::initialize(program, vec![]); | ||||||
|  |         c.run(); | ||||||
|  |         assert_eq!(c.output[0], 1125899906842624); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn day9_relative_mode_input() { | ||||||
|  |         let program = vec![109, -2, 203, 2, 99]; | ||||||
|  |         let mut c = Computer::initialize(program, vec![1312]); | ||||||
|  |         c.run(); | ||||||
|  |         assert_eq!(c.mem_get(0), 1312); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     #[test] | ||||||
|  |     fn day9() { | ||||||
|  |         let program = vec![1102,34463338,34463338,63,1007,63,34463338,63,1005,63,53,1101,0,3,1000,109,988,209,12,9,1000,209,6,209,3,203,0,1008,1000,1,63,1005,63,65,1008,1000,2,63,1005,63,904,1008,1000,0,63,1005,63,58,4,25,104,0,99,4,0,104,0,99,4,17,104,0,99,0,0,1102,1,432,1027,1101,439,0,1026,1101,0,36,1010,1101,0,34,1018,1102,278,1,1029,1101,0,24,1002,1102,1,20,1016,1102,1,31,1011,1102,319,1,1024,1102,21,1,1012,1102,1,763,1022,1102,1,25,1007,1101,0,287,1028,1102,32,1,1008,1101,0,22,1013,1102,38,1,1001,1101,0,314,1025,1102,35,1,1009,1102,1,23,1015,1102,39,1,1019,1102,27,1,1000,1102,1,37,1003,1102,1,28,1017,1101,0,0,1020,1101,0,29,1004,1102,1,30,1006,1102,1,756,1023,1102,1,33,1005,1101,0,1,1021,1102,26,1,1014,109,13,2108,28,-7,63,1005,63,201,1001,64,1,64,1105,1,203,4,187,1002,64,2,64,109,8,21107,40,41,-3,1005,1018,225,4,209,1001,64,1,64,1105,1,225,1002,64,2,64,109,-3,1206,2,239,4,231,1105,1,243,1001,64,1,64,1002,64,2,64,109,-21,1201,6,0,63,1008,63,35,63,1005,63,267,1001,64,1,64,1105,1,269,4,249,1002,64,2,64,109,35,2106,0,-4,4,275,1001,64,1,64,1105,1,287,1002,64,2,64,109,-11,1205,-1,303,1001,64,1,64,1105,1,305,4,293,1002,64,2,64,109,8,2105,1,-5,4,311,1106,0,323,1001,64,1,64,1002,64,2,64,109,-7,21108,41,38,-6,1005,1016,339,1106,0,345,4,329,1001,64,1,64,1002,64,2,64,109,2,21102,42,1,-8,1008,1016,45,63,1005,63,369,1001,64,1,64,1105,1,371,4,351,1002,64,2,64,109,-14,21101,43,0,1,1008,1011,43,63,1005,63,397,4,377,1001,64,1,64,1106,0,397,1002,64,2,64,109,-8,21101,44,0,8,1008,1010,47,63,1005,63,417,1105,1,423,4,403,1001,64,1,64,1002,64,2,64,109,25,2106,0,0,1001,64,1,64,1105,1,441,4,429,1002,64,2,64,109,-20,2107,37,-6,63,1005,63,463,4,447,1001,64,1,64,1106,0,463,1002,64,2,64,109,8,2108,25,-8,63,1005,63,485,4,469,1001,64,1,64,1106,0,485,1002,64,2,64,109,-1,21107,45,44,-1,1005,1013,505,1001,64,1,64,1106,0,507,4,491,1002,64,2,64,109,-11,1207,-1,25,63,1005,63,529,4,513,1001,64,1,64,1106,0,529,1002,64,2,64,109,23,1206,-5,545,1001,64,1,64,1106,0,547,4,535,1002,64,2,64,109,-31,2102,1,5,63,1008,63,27,63,1005,63,569,4,553,1106,0,573,1001,64,1,64,1002,64,2,64,109,27,21102,46,1,-9,1008,1013,46,63,1005,63,595,4,579,1105,1,599,1001,64,1,64,1002,64,2,64,109,-26,2101,0,6,63,1008,63,24,63,1005,63,625,4,605,1001,64,1,64,1106,0,625,1002,64,2,64,109,5,1208,0,37,63,1005,63,645,1001,64,1,64,1105,1,647,4,631,1002,64,2,64,109,7,2102,1,-3,63,1008,63,31,63,1005,63,671,1001,64,1,64,1105,1,673,4,653,1002,64,2,64,109,2,1202,-5,1,63,1008,63,33,63,1005,63,699,4,679,1001,64,1,64,1105,1,699,1002,64,2,64,109,-4,2101,0,-3,63,1008,63,35,63,1005,63,719,1105,1,725,4,705,1001,64,1,64,1002,64,2,64,109,-5,1207,4,32,63,1005,63,741,1106,0,747,4,731,1001,64,1,64,1002,64,2,64,109,29,2105,1,-7,1001,64,1,64,1106,0,765,4,753,1002,64,2,64,109,-26,2107,36,5,63,1005,63,781,1105,1,787,4,771,1001,64,1,64,1002,64,2,64,109,10,1201,-6,0,63,1008,63,32,63,1005,63,809,4,793,1106,0,813,1001,64,1,64,1002,64,2,64,109,3,21108,47,47,-5,1005,1012,835,4,819,1001,64,1,64,1106,0,835,1002,64,2,64,109,-24,1202,9,1,63,1008,63,25,63,1005,63,859,1001,64,1,64,1106,0,861,4,841,1002,64,2,64,109,19,1205,9,875,4,867,1106,0,879,1001,64,1,64,1002,64,2,64,109,-3,1208,-1,32,63,1005,63,897,4,885,1106,0,901,1001,64,1,64,4,64,99,21102,27,1,1,21101,915,0,0,1105,1,922,21201,1,60043,1,204,1,99,109,3,1207,-2,3,63,1005,63,964,21201,-2,-1,1,21102,1,942,0,1106,0,922,21202,1,1,-1,21201,-2,-3,1,21101,957,0,0,1106,0,922,22201,1,-1,-2,1105,1,968,22102,1,-2,-2,109,-3,2105,1,0]; | ||||||
|  |         let mut c = Computer::initialize(program, vec![1]); | ||||||
|  |         c.run(); | ||||||
|  |         assert_eq!(c.output.len(), 1); | ||||||
|  |         assert_eq!(c.output[0], 3063082071); | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue