Add 9 first days

This commit is contained in:
2021-01-08 23:41:37 +11:00
parent 4846e7c811
commit 2fd73ae5d1
49 changed files with 9734 additions and 0 deletions

1
8-handheld_halting/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/target

70
8-handheld_halting/Cargo.lock generated Normal file
View File

@@ -0,0 +1,70 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "anyhow"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee67c11feeac938fae061b232e38e0b6d94f97a9df10e6271319325ac4c56a86"
[[package]]
name = "handheld_halting"
version = "0.1.0"
dependencies = [
"anyhow",
"thiserror",
]
[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
dependencies = [
"proc-macro2",
]
[[package]]
name = "syn"
version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4211ce9909eb971f111059df92c45640aad50a619cf55cd76476be803c4c68e6"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "thiserror"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"

View File

@@ -0,0 +1,11 @@
[package]
name = "handheld_halting"
version = "0.1.0"
authors = ["Guilhem MARION <gmarion@netc.fr>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.37"
thiserror = "1.0.23"

View File

@@ -0,0 +1,623 @@
acc -17
nop +318
jmp +1
acc -10
jmp +394
acc +43
acc +47
nop +570
jmp +176
acc -9
jmp +322
jmp +73
acc +4
acc -4
jmp +460
jmp +228
acc +25
acc +39
jmp +50
acc -12
acc -14
nop +275
jmp +489
acc -11
jmp +338
acc +21
acc +10
jmp +1
acc +20
jmp +445
acc +7
jmp +419
acc -8
acc +32
jmp +181
acc +19
acc +5
acc +46
jmp +417
acc +28
acc +23
acc +16
jmp +225
jmp +317
jmp +309
jmp +69
acc -6
acc -6
jmp +127
acc +49
nop -38
jmp +467
acc +0
acc -12
acc -14
jmp -46
acc +14
acc +2
acc +2
jmp +311
acc +33
jmp +364
nop +234
acc +24
acc +37
acc +18
jmp +22
jmp +303
jmp +414
jmp +318
acc +22
acc +27
jmp +1
jmp +150
acc +34
acc +15
nop +200
acc +6
jmp +320
nop +534
acc +29
jmp +147
nop -20
jmp +255
jmp +10
acc -15
acc +3
jmp +338
nop +362
acc -4
jmp +1
jmp +286
acc -1
jmp +497
acc -4
acc +23
acc +4
jmp +400
acc +35
acc +50
jmp +133
acc -17
jmp -90
jmp +7
acc -17
jmp +472
acc +20
jmp +280
jmp +133
jmp -15
jmp +16
acc -19
acc -2
jmp -64
acc -17
jmp +1
jmp +385
acc -5
acc +34
jmp +382
acc +24
acc -17
acc +0
acc +15
jmp +466
jmp +300
acc +16
jmp +302
nop +479
acc +16
jmp +71
acc +23
jmp +1
acc +8
jmp +154
jmp +410
acc -8
jmp +402
acc +48
acc +42
acc +22
acc +35
jmp +50
jmp -7
acc -13
acc +37
acc +24
jmp +243
jmp +410
acc -3
acc +45
jmp +416
acc +2
acc +25
jmp -109
jmp -41
jmp +318
acc -8
acc -12
jmp +169
nop +393
acc +7
acc -12
acc +35
jmp +381
acc +41
nop -98
acc +15
acc -19
jmp +218
acc +24
acc +47
jmp +65
acc +29
jmp -129
acc +23
acc -13
nop +60
jmp -26
nop -4
acc -5
acc +13
nop -12
jmp -13
jmp -53
acc +21
jmp +276
nop -27
jmp +165
acc +42
nop +43
jmp +1
acc +26
acc +22
acc -3
jmp +405
acc +29
nop -118
acc +21
nop -190
jmp +217
acc -1
nop +223
acc -8
acc +45
jmp +49
acc +8
acc +22
jmp +209
acc +44
jmp +66
acc +7
acc -7
acc +48
jmp +318
nop +398
acc +2
jmp +16
nop +207
nop +358
acc +45
acc +48
jmp +267
nop +248
acc +26
jmp +307
acc +27
jmp -197
jmp -68
acc +34
acc +25
acc -13
jmp +133
jmp -77
acc -13
acc +10
jmp -193
jmp -62
acc +4
acc -14
jmp +261
jmp +151
jmp +208
acc -10
jmp +40
acc +31
jmp -216
acc +23
acc +34
jmp +364
nop +205
acc -3
acc +14
jmp +59
nop +359
acc -4
jmp +1
jmp -248
acc +47
acc +35
jmp +184
acc +16
nop -92
acc -12
jmp +354
acc +27
jmp -152
acc -14
acc -16
acc +43
jmp +147
acc +45
acc +24
acc +6
nop -46
jmp +21
acc +26
jmp +1
jmp +293
acc -8
acc +12
acc -19
acc -9
jmp +94
jmp +299
acc +10
acc -2
jmp +75
acc -7
acc +3
acc +47
jmp +171
acc +16
acc +44
acc -3
jmp +14
acc +30
acc +34
jmp -178
acc +35
nop -238
acc +39
jmp +1
jmp -133
acc +34
acc -6
jmp -276
acc +1
jmp -207
acc +10
jmp -43
jmp -302
acc -1
nop -29
jmp +1
acc +17
jmp -281
acc +17
jmp -109
jmp +1
acc +13
nop -9
jmp +245
acc +5
nop -15
acc +3
acc +7
jmp +65
acc -11
jmp -313
acc +47
jmp +29
jmp -289
acc +18
acc -17
nop +73
acc -12
jmp +80
acc +32
acc -4
acc +3
jmp -126
acc +16
jmp -275
nop -188
acc -3
acc +14
jmp -155
acc +33
acc -19
nop -166
acc +20
jmp +30
nop -169
acc +49
nop +168
jmp -24
nop -345
acc +34
jmp -40
jmp -56
jmp +29
jmp +191
acc +24
jmp +219
acc +34
acc +27
acc +11
jmp -260
jmp -339
acc +15
nop +16
jmp +1
jmp +138
jmp +1
jmp +1
jmp +14
acc -11
acc +45
jmp -19
acc +0
jmp +27
acc +0
nop +128
jmp -65
nop -23
jmp -318
jmp -325
jmp +1
jmp -229
jmp -270
jmp -137
acc +34
acc +7
jmp +1
jmp -346
acc +18
jmp +37
acc +40
acc -16
nop -146
acc +35
jmp -12
acc +1
acc +27
acc +44
acc +8
jmp -276
acc +16
acc +42
nop -342
acc +13
jmp -165
acc -11
acc -17
acc -10
jmp -26
acc +10
acc +43
jmp -276
acc +5
acc +34
acc +17
acc -9
jmp +99
acc +29
jmp -370
acc -11
jmp -412
acc +47
acc +21
acc -12
jmp -136
jmp -124
acc +12
acc +0
acc +25
acc +27
jmp -290
acc +5
acc +49
acc +32
nop +29
jmp -202
nop -296
acc -12
acc +9
acc +21
jmp +23
jmp -345
acc +26
nop -123
jmp -373
nop +118
jmp +43
acc -15
jmp -386
jmp +1
nop -370
acc +47
nop -141
jmp -426
acc +42
acc +12
acc +4
nop -103
jmp -122
acc +23
acc -4
acc +11
jmp -314
jmp -73
nop -1
jmp -411
acc +13
acc +9
nop -372
jmp -293
acc +46
acc +3
acc -1
jmp +86
acc +36
jmp +100
acc +27
acc +49
nop -4
acc +47
jmp -445
acc +31
acc +47
acc -11
acc +14
jmp -181
nop -438
acc +31
jmp -428
nop -115
nop -244
jmp -464
jmp -29
nop -240
jmp -241
acc -12
jmp -329
nop +78
acc +6
jmp +1
acc +49
jmp -322
jmp -133
acc +20
nop -83
acc +35
acc +29
jmp -41
acc +15
jmp -46
jmp -29
acc +45
acc -14
acc +21
jmp -366
nop +84
acc -6
acc +25
acc -17
jmp -326
acc -5
nop -159
acc +5
jmp -171
acc +42
jmp -28
acc +42
acc -11
acc +45
acc +19
jmp -305
acc +38
acc -13
acc -16
jmp -134
acc +45
jmp -256
acc -15
acc -18
acc +28
jmp -114
acc -11
acc +47
nop -420
jmp -90
nop -330
jmp +13
acc -15
acc +9
jmp -159
acc -12
acc +0
acc +0
jmp -538
acc +31
acc +24
acc +32
acc -16
jmp -95
jmp -466
acc +19
acc +2
jmp -172
acc -12
jmp -207
acc +39
acc +18
acc +5
jmp -211
nop -507
jmp +1
jmp -197
nop -227
acc +28
jmp -494
acc +22
acc +2
acc -14
jmp -377
acc +8
acc +29
jmp -573
acc -17
acc +14
acc +29
acc +11
jmp -351
acc +9
nop -540
acc +30
nop -344
jmp -564
acc -4
nop -465
jmp -293
acc -18
acc +5
acc +29
jmp -302
acc -17
acc +14
acc +2
acc -11
jmp -527
jmp -563
acc +14
acc +10
jmp -505
acc +43
jmp -188
nop -448
acc +44
acc +3
acc +16
jmp +1

View File

@@ -0,0 +1,246 @@
use std::str::FromStr;
use anyhow::Result;
#[derive(Debug, Clone, PartialEq)]
enum ISet {
Acc,
Jmp,
Nop,
}
#[derive(Debug, Clone)]
struct Instruction {
execd: bool,
instr: ISet,
arg: i64
}
#[derive(Debug, thiserror::Error)]
enum ParseError {
#[error("Expected {0}")]
Expected(&'static str)
}
impl FromStr for Instruction {
type Err = ParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut tokens = s.lines()
.next()
.ok_or(ParseError::Expected("one line"))?
.split_whitespace();
match tokens.next().ok_or(ParseError::Expected("instruction"))? {
"acc" => {
let arg = tokens
.next()
.ok_or(ParseError::Expected("acc argument"))?
.parse()
.unwrap();
Ok(Instruction {
execd: false,
instr: ISet::Acc,
arg,
})
},
"nop" => {
let arg = tokens
.next()
.ok_or(ParseError::Expected("acc argument"))?
.parse()
.unwrap();
Ok(Instruction {
execd: false,
instr: ISet::Nop,
arg, // For part 1 at least NOP args are useless
})
},
"jmp" => {
let arg = tokens
.next()
.ok_or(ParseError::Expected("acc argument"))?
.parse()
.unwrap();
Ok(Instruction {
execd: false,
instr: ISet::Jmp,
arg,
})
},
_ => Err(ParseError::Expected("acc, nop or jmp instruction"))
}
}
}
impl Instruction {
fn exec(&mut self, pc: &mut usize, acc: &mut i64) {
self.execd = true;
match self.instr {
ISet::Acc => {
*acc += self.arg;
*pc += 1;
}
ISet::Jmp => {
// Expect this to panic hard if you underflow :3
*pc = ((*pc as i64) + self.arg) as usize;
}
ISet::Nop => {
*pc += 1;
}
}
}
}
#[derive(Debug, Clone)]
struct Program {
prog: Vec<Instruction>,
pc: usize,
acc: i64,
}
impl Program {
fn load(s: &str) -> Result<Program, ParseError> {
let loaded_program: Vec<Instruction> = s
.lines()
.map(|l| Instruction::from_str(l))
.collect::<Result<Vec<Instruction>, ParseError>>()?;
Ok(
Self {
prog: loaded_program,
pc: 0,
acc: 0,
}
)
}
fn reset(&mut self) {
self.pc = 0;
self.acc = 0;
for mut i in self.prog.iter_mut() {
i.execd = false;
}
}
/// Returns whether execution finished :
/// Normally (true) - executing one instruction after the last one
/// Or abnormalaly (false) - looping forever or executing random
/// instructions
fn exec_until_loop(&mut self) -> bool {
let pc_stop = self.prog.len();
loop {
// Terminate on infinite loop
if self.prog[self.pc].execd {
println!("Infinite loop !");
return false;
}
self.prog[self.pc].exec(&mut self.pc, &mut self.acc);
// Terminate on success
if self.pc == pc_stop {
println!("Good pc !");
return true;
}
// Terminate on corrupted pc
else if !(0..=pc_stop).contains(&(self.pc)) {
println!("Corrupted pc !");
return false;
}
}
}
fn find_corrupted_instruction(&mut self) -> Option<i64> {
// Test jmps -> nops
self.reset();
for j in (0..self.prog.len())
.filter(|&i| self.prog[i].instr == ISet::Jmp)
{
println!("Switch jmp-nop at pos {}", j);
let mut pclone = self.clone();
pclone.prog[j].instr = ISet::Nop;
if pclone.exec_until_loop() {
return Some(pclone.acc);
}
}
// Test nops -> jmps
for n in (0..self.prog.len())
.filter(|&i| self.prog[i].instr == ISet::Nop)
{
println!("Switch nop-jmp at pos {}", n);
let mut pclone = self.clone();
pclone.prog[n].instr = ISet::Jmp;
if pclone.exec_until_loop() {
return Some(pclone.acc);
}
}
None
}
}
fn main() {
let input = include_str!("../data/input");
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
println!("Acc before program gets into second loop : {}", prog.acc);
println!("Acc after the program is set to terminate : {}", prog.find_corrupted_instruction().unwrap());
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_nop() {
let input = r"nop +0";
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
assert_eq!(prog.acc, 0)
}
#[test]
fn test_acc() {
let input = r"acc +5";
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
assert_eq!(prog.acc, 5)
}
#[test]
fn test_jmp() {
let input = r"jmp +2
acc +1
acc +1";
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
assert_eq!(prog.acc, 1)
}
#[test]
fn test_short_loop() {
let input = r"acc +1
jmp +2
acc +1
acc +1
jmp -4";
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
assert_eq!(prog.acc, 2)
}
#[test]
fn test_exec() {
let input = r"nop +0
acc +1
jmp +4
acc +3
jmp -3
acc -99
acc +1
jmp -4
acc +6";
let mut prog = Program::load(input).unwrap();
prog.exec_until_loop();
assert_eq!(prog.acc, 5)
}
}