Merge remote-tracking branch '2019/main'

This commit is contained in:
Kienan Stewart 2022-05-16 23:26:11 -04:00
commit c27c60ce9a
44 changed files with 3717 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
bin/
zig-out/
zig-cache/
target/

13
day1/Makefile Normal file
View File

@ -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

27
day1/build.zig Normal file
View File

@ -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);
}

100
day1/input Normal file
View File

@ -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

29
day1/main.rs Normal file
View File

@ -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);
}

36
day1/src/main.zig Normal file
View File

@ -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});
}

7
day2/Cargo.lock generated Normal file
View File

@ -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"

8
day2/Cargo.toml Normal file
View File

@ -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]

1
day2/input Normal file
View File

@ -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

105
day2/src/main.rs Normal file
View File

@ -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);
}
}

7
day3/Cargo.lock generated Normal file
View File

@ -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"

8
day3/Cargo.toml Normal file
View File

@ -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]

2
day3/input Normal file
View File

@ -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

178
day3/src/main.rs Normal file
View File

@ -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 {
}

2
day3/testinput Normal file
View File

@ -0,0 +1,2 @@
R8,U5,L5,D3
U7,R6,D4,L4

7
day4/Cargo.lock generated Normal file
View File

@ -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"

8
day4/Cargo.toml Normal file
View File

@ -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]

101
day4/src/main.rs Normal file
View File

@ -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);
}

14
day5/Cargo.lock generated Normal file
View File

@ -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"

9
day5/Cargo.toml Normal file
View File

@ -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"}

1
day5/input Normal file
View File

@ -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

29
day5/src/main.rs Normal file
View File

@ -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);
}

7
day6/Cargo.lock generated Normal file
View File

@ -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"

8
day6/Cargo.toml Normal file
View File

@ -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]

1805
day6/input Normal file

File diff suppressed because it is too large Load Diff

169
day6/src/main.rs Normal file
View File

@ -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
}
}

11
day6/test Normal file
View File

@ -0,0 +1,11 @@
COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L

13
day6/test2 Normal file
View File

@ -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

30
day7/Cargo.lock generated Normal file
View File

@ -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",
]

10
day7/Cargo.toml Normal file
View File

@ -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"

132
day7/src/#main.rs# Normal file
View File

@ -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);
}
}

1
day7/src/.#main.rs Symbolic link
View File

@ -0,0 +1 @@
kienan@monolith.244424:1652264161

132
day7/src/main.rs Normal file
View File

@ -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);
}
}

7
day8/Cargo.lock generated Normal file
View File

@ -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"

8
day8/Cargo.toml Normal file
View File

@ -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]

1
day8/input Normal file

File diff suppressed because one or more lines are too long

122
day8/src/main.rs Normal file
View File

@ -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);
}
}

14
day9/Cargo.lock generated Normal file
View File

@ -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"

9
day9/Cargo.toml Normal file
View File

@ -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"}

1
day9/input Normal file
View File

@ -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

26
day9/src/main.rs Normal file
View File

@ -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]);
}
}

7
icc/Cargo.lock generated Normal file
View File

@ -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"

8
icc/Cargo.toml Normal file
View File

@ -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]

500
icc/src/lib.rs Normal file
View File

@ -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);
}
}