Compare commits
	
		
			13 Commits
		
	
	
		
			main
			...
			b39f312e9f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b39f312e9f | |||
| f663a57db8 | |||
| 33ba8d72f4 | |||
| 29a122c3ff | |||
| dafe576fc9 | |||
| 900f01913f | |||
| f952db1e0f | |||
| 1ec3c9c939 | |||
| 27e9e60089 | |||
| d06a694543 | |||
| d655185336 | |||
| f468af10f4 | |||
| 4d1477d7c1 | 
							
								
								
									
										65
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										65
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @@ -2,25 +2,84 @@ | |||||||
| # It is not intended for manual editing. | # It is not intended for manual editing. | ||||||
| version = 4 | version = 4 | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "aho-corasick" | ||||||
|  | version = "1.1.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" | ||||||
|  | dependencies = [ | ||||||
|  |  "memchr", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "either" | ||||||
|  | version = "1.13.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "genaoc" | name = "genaoc" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "itertools" | ||||||
|  | version = "0.13.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" | ||||||
|  | dependencies = [ | ||||||
|  |  "either", | ||||||
|  | ] | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "md5" | name = "md5" | ||||||
| version = "0.7.0" | version = "0.7.0" | ||||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
| checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" | checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "memchr" | ||||||
|  | version = "2.7.4" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "regex" | ||||||
|  | version = "1.11.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" | ||||||
|  | dependencies = [ | ||||||
|  |  "aho-corasick", | ||||||
|  |  "memchr", | ||||||
|  |  "regex-automata", | ||||||
|  |  "regex-syntax", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "regex-automata" | ||||||
|  | version = "0.4.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" | ||||||
|  | dependencies = [ | ||||||
|  |  "aho-corasick", | ||||||
|  |  "memchr", | ||||||
|  |  "regex-syntax", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [[package]] | ||||||
|  | name = "regex-syntax" | ||||||
|  | version = "0.8.5" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "utils" | name = "utils" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| source = "git+https://git.plobos.xyz/projects/PuzzleUtils.git#49b0f24c1bdc2c04df237634607df15f19fb3ead" |  | ||||||
|  |  | ||||||
| [[package]] | [[package]] | ||||||
| name = "y2015" | name = "y2015" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|  |  "itertools", | ||||||
|  "md5", |  "md5", | ||||||
|  "utils", |  "utils", | ||||||
| ] | ] | ||||||
| @@ -60,3 +119,7 @@ version = "0.1.0" | |||||||
| [[package]] | [[package]] | ||||||
| name = "y2024" | name = "y2024" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "regex", | ||||||
|  |  "utils", | ||||||
|  | ] | ||||||
|   | |||||||
| @@ -19,4 +19,6 @@ members = [ | |||||||
| ] | ] | ||||||
|  |  | ||||||
| [workspace.dependencies] | [workspace.dependencies] | ||||||
| utils = { git = "https://git.plobos.xyz/projects/PuzzleUtils.git" } | utils = { path = "../utils" } | ||||||
|  | itertools = "0.13.0" | ||||||
|  | regex = "1.11.1" | ||||||
|   | |||||||
							
								
								
									
										179
									
								
								day22.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								day22.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | |||||||
|  | 'use strict'; | ||||||
|  |  | ||||||
|  | var bossStats = { | ||||||
|  | 	hp: 71, | ||||||
|  | 	damageAmt: 10, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class Player { | ||||||
|  | 	constructor(initial, isWizard) { | ||||||
|  | 		this.history = []; | ||||||
|  | 		this.initial = initial; | ||||||
|  | 		this.isWizard = !!isWizard; | ||||||
|  |  | ||||||
|  | 		if (this.isWizard) { | ||||||
|  | 			this.spells = [ | ||||||
|  | 				{ | ||||||
|  | 					cost: 53, | ||||||
|  | 					effect: (m, o) => o.damage(4), | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					cost: 73, | ||||||
|  | 					effect: (m, o) => { o.damage(2); m.hp += 2; }, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					cost: 113, | ||||||
|  | 					start: (m, o) => m.armor += 7, | ||||||
|  | 					effect: (m, o) => { }, | ||||||
|  | 					end: (m, o) => m.armor -= 7, | ||||||
|  | 					duration: 6, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					cost: 173, | ||||||
|  | 					effect: (m, o) => o.damage(3), | ||||||
|  | 					duration: 6, | ||||||
|  | 				}, | ||||||
|  | 				{ | ||||||
|  | 					cost: 229, | ||||||
|  | 					effect: (m, o) => m.mana += 101, | ||||||
|  | 					duration: 5, | ||||||
|  | 				}, | ||||||
|  | 			]; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		this.start(); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	attack(opponent, spellIdx) { | ||||||
|  | 		if (!this.isWizard) { | ||||||
|  | 			opponent.damage(this.damageAmt); | ||||||
|  | 		} else { | ||||||
|  | 			this.history.push(spellIdx); | ||||||
|  | 			var spell = this.spells[spellIdx]; | ||||||
|  | 			this.spent += spell.cost; | ||||||
|  | 			this.mana -= spell.cost; | ||||||
|  |  | ||||||
|  | 			if (spell.duration) { | ||||||
|  | 				var newSpell = { | ||||||
|  | 					idx: spellIdx, | ||||||
|  | 					effect: spell.effect, | ||||||
|  | 					duration: spell.duration, | ||||||
|  | 				}; | ||||||
|  | 				if (spell.start) { | ||||||
|  | 					spell.start(this, opponent); | ||||||
|  | 				} | ||||||
|  | 				if (spell.end) { | ||||||
|  | 					newSpell.end = spell.end; | ||||||
|  | 				} | ||||||
|  | 				this.activeSpells.push(newSpell); | ||||||
|  | 			} else { | ||||||
|  | 				spell.effect(this, opponent); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	damage(n) { | ||||||
|  | 		this.hp -= Math.max(1, n - this.armor); | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	duplicate() { | ||||||
|  | 		var newPlayer = new Player(this.initial, this.isWizard); | ||||||
|  | 		newPlayer.hp = this.hp; | ||||||
|  | 		newPlayer.spent = this.spent; | ||||||
|  | 		newPlayer.armor = this.armor; | ||||||
|  | 		newPlayer.turn = this.turn; | ||||||
|  | 		for (var i = 0; i < this.activeSpells.length; i++) { | ||||||
|  | 			newPlayer.activeSpells.push(Object.assign({}, this.activeSpells[i])); | ||||||
|  | 		} | ||||||
|  | 		for (var i = 0; i < this.history.length; i++) { | ||||||
|  | 			newPlayer.history.push(this.history[i]); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (this.isWizard) | ||||||
|  | 			newPlayer.mana = this.mana; | ||||||
|  | 		else | ||||||
|  | 			newPlayer.damageAmt = this.damageAmt; | ||||||
|  |  | ||||||
|  | 		return newPlayer; | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	takeTurn(opponent) { | ||||||
|  | 		this.turn++; | ||||||
|  |  | ||||||
|  | 		for (var i = 0; i < this.activeSpells.length; i++) { | ||||||
|  | 			var spell = this.activeSpells[i]; | ||||||
|  |  | ||||||
|  | 			if (spell.duration > 0) { | ||||||
|  | 				spell.effect(this, opponent); | ||||||
|  | 				spell.duration--; | ||||||
|  |  | ||||||
|  | 				if (spell.duration === 0 && spell.end) { | ||||||
|  | 					spell.end(this, opponent); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	start() { | ||||||
|  | 		this.hp = this.initial.hp; | ||||||
|  | 		this.spent = 0; | ||||||
|  | 		this.armor = 0; | ||||||
|  | 		this.turn = 0; | ||||||
|  | 		this.activeSpells = []; | ||||||
|  | 		if (this.isWizard) | ||||||
|  | 			this.mana = this.initial.mana; | ||||||
|  | 		else | ||||||
|  | 			this.damageAmt = this.initial.damageAmt; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | var me = new Player({ hp: 50, mana: 500 }, true); | ||||||
|  | var boss = new Player(bossStats); | ||||||
|  |  | ||||||
|  | var cheapestSpent = Infinity; | ||||||
|  |  | ||||||
|  | function playAllGames(me, boss, partTwo, depth) { | ||||||
|  | 	depth = depth || 0; | ||||||
|  | 	for (var i = 0; i < me.spells.length; i++) { | ||||||
|  | 		var spellMatch = false; | ||||||
|  | 		for (var j = 0; j < me.activeSpells.length; j++) { | ||||||
|  | 			if (me.activeSpells[j].duration > 1 && i === me.activeSpells[j].idx) { | ||||||
|  | 				spellMatch = true;; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (spellMatch) | ||||||
|  | 			continue; | ||||||
|  | 		if (me.spells[i].cost > me.mana) { | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		var newMe = me.duplicate(); | ||||||
|  | 		var newBoss = boss.duplicate(); | ||||||
|  |  | ||||||
|  | 		if (partTwo) | ||||||
|  | 			newMe.hp--; | ||||||
|  |  | ||||||
|  | 		newMe.takeTurn(newBoss); | ||||||
|  | 		newBoss.takeTurn(newMe); | ||||||
|  | 		newMe.attack(newBoss, i); | ||||||
|  |  | ||||||
|  | 		newMe.takeTurn(newBoss); | ||||||
|  | 		newBoss.takeTurn(newMe); | ||||||
|  | 		newBoss.attack(newMe); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | 		if (newBoss.hp <= 0) { | ||||||
|  | 			cheapestSpent = Math.min(cheapestSpent, newMe.spent); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if (newMe.hp > (partTwo ? 1 : 0) && newBoss.hp > 0 && newMe.spent < cheapestSpent) | ||||||
|  | 			playAllGames(newMe, newBoss, partTwo, depth + 1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | playAllGames(me, boss); | ||||||
|  | console.log('Part One:', cheapestSpent); | ||||||
|  | cheapestSpent = Infinity; | ||||||
|  | playAllGames(me, boss, true); | ||||||
|  | console.log('Part Two:', cheapestSpent); | ||||||
							
								
								
									
										4
									
								
								justfile
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								justfile
									
									
									
									
									
								
							| @@ -1,8 +1,8 @@ | |||||||
| gen year day: | gen year *day: | ||||||
| 	cargo run -- {{year}} {{day}} | 	cargo run -- {{year}} {{day}} | ||||||
|  |  | ||||||
| run year day: | run year day: | ||||||
| 	cargo run --package y{{year}} --bin d{{day}} | 	cargo run --package y{{year}} --bin d{{day}} | ||||||
|  |  | ||||||
| test year day *part='1': | test year day *part='1': | ||||||
| 	cargo test --package y{{year}} days::d{{day}}::tests::part{{part}} -- --nocapture | 	cargo test --package y{{year}} --lib days::d{{day}}::tests::part{{part}} -- --nocapture | ||||||
|   | |||||||
| @@ -6,3 +6,4 @@ edition = "2021" | |||||||
| [dependencies] | [dependencies] | ||||||
| md5 = "0.7.0" | md5 = "0.7.0" | ||||||
| utils = { workspace = true } | utils = { workspace = true } | ||||||
|  | itertools = { workspace = true } | ||||||
|   | |||||||
							
								
								
									
										49
									
								
								y2015/resources/23_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								y2015/resources/23_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | |||||||
|  | jio a, +19 | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | jmp +23 | ||||||
|  | tpl a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | inc a | ||||||
|  | tpl a | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | jio a, +8 | ||||||
|  | inc b | ||||||
|  | jie a, +4 | ||||||
|  | tpl a | ||||||
|  | inc a | ||||||
|  | jmp +2 | ||||||
|  | hlf a | ||||||
|  | jmp -7 | ||||||
							
								
								
									
										29
									
								
								y2015/resources/24_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								y2015/resources/24_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | 1 | ||||||
|  | 2 | ||||||
|  | 3 | ||||||
|  | 5 | ||||||
|  | 7 | ||||||
|  | 13 | ||||||
|  | 17 | ||||||
|  | 19 | ||||||
|  | 23 | ||||||
|  | 29 | ||||||
|  | 31 | ||||||
|  | 37 | ||||||
|  | 41 | ||||||
|  | 43 | ||||||
|  | 53 | ||||||
|  | 59 | ||||||
|  | 61 | ||||||
|  | 67 | ||||||
|  | 71 | ||||||
|  | 73 | ||||||
|  | 79 | ||||||
|  | 83 | ||||||
|  | 89 | ||||||
|  | 97 | ||||||
|  | 101 | ||||||
|  | 103 | ||||||
|  | 107 | ||||||
|  | 109 | ||||||
|  | 113 | ||||||
							
								
								
									
										1
									
								
								y2015/resources/25_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								y2015/resources/25_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | To continue, please consult the code grid in the manual.  Enter the code at row 2981, column 3075. | ||||||
							
								
								
									
										20
									
								
								y2015/src/bin/d23.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								y2015/src/bin/d23.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | use std::fs; | ||||||
|  |  | ||||||
|  | use y2015::days::d23; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  |     part2(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/23_input.txt")).unwrap(); | ||||||
|  |     println!("{:?}", d23::process_part1(&content)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part2() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/23_input.txt")).unwrap(); | ||||||
|  |     println!("{:?}", d23::process_part2(&content)); | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								y2015/src/bin/d24.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								y2015/src/bin/d24.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | use std::fs; | ||||||
|  |  | ||||||
|  | use y2015::days::d24; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  |     part2(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/24_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d24::process_part1(&content)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part2() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/24_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d24::process_part2(&content)); | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								y2015/src/bin/d25.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								y2015/src/bin/d25.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | |||||||
|  | use y2015::days::d25; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     println!("{}", d25::process_part1(3075, 2981)); | ||||||
|  | } | ||||||
| @@ -24,20 +24,20 @@ pub fn process_part1(input: &str) -> u32 { | |||||||
|     }; |     }; | ||||||
|     let mut smallest = u32::MAX; |     let mut smallest = u32::MAX; | ||||||
|     let mut leafs = vec![start]; |     let mut leafs = vec![start]; | ||||||
|     let mut test = 0; |  | ||||||
|     println!("start"); |     println!("start"); | ||||||
|  |     // Playing, Win, Loss | ||||||
|  |     let mut stats = (0, 0, 0); | ||||||
|     loop { |     loop { | ||||||
|         println!("iter: {test},"); |  | ||||||
|         let current_leafs = leafs.clone(); |         let current_leafs = leafs.clone(); | ||||||
|         println!("leaf count: {}", current_leafs.len()); |  | ||||||
|         leafs.clear(); |         leafs.clear(); | ||||||
|         // create potential rounds |         // create potential rounds | ||||||
|         for leaf in current_leafs { |         for leaf in current_leafs { | ||||||
|             if leaf.state == State::Playing { |             if leaf.state == State::Playing { | ||||||
|                 //println!("try for leaf"); |  | ||||||
|                 for spell in Spell::get_all() { |                 for spell in Spell::get_all() { | ||||||
|                     match spell.name { |                     match spell.name { | ||||||
|                         SpellID::MagicMissile | SpellID::Drain => {} |                         SpellID::MagicMissile | SpellID::Drain => { | ||||||
|  |                             leafs.push(leaf.use_spell(spell, false)); | ||||||
|  |                         } | ||||||
|                         SpellID::Shield => { |                         SpellID::Shield => { | ||||||
|                             if !leaf |                             if !leaf | ||||||
|                                 .player |                                 .player | ||||||
| @@ -45,68 +45,151 @@ pub fn process_part1(input: &str) -> u32 { | |||||||
|                                 .iter() |                                 .iter() | ||||||
|                                 .any(|effect| effect.name == SpellID::Shield && effect.duration > 1) |                                 .any(|effect| effect.name == SpellID::Shield && effect.duration > 1) | ||||||
|                             { |                             { | ||||||
|                                 continue; |                                 leafs.push(leaf.use_spell(spell, false)); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         SpellID::Poison => { |                         SpellID::Poison => { | ||||||
|                             if !leaf |                             if !leaf | ||||||
|                                 .player |                                 .boss | ||||||
|                                 .status_effects |                                 .status_effects | ||||||
|                                 .iter() |                                 .iter() | ||||||
|                                 .any(|effect| effect.name == SpellID::Poison && effect.duration > 1) |                                 .any(|effect| effect.name == SpellID::Poison && effect.duration > 1) | ||||||
|                             { |                             { | ||||||
|                                 continue; |                                 leafs.push(leaf.use_spell(spell, false)); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                         SpellID::Recharge => { |                         SpellID::Recharge => { | ||||||
|                             if !leaf.player.status_effects.iter().any(|effect| { |                             if !leaf.player.status_effects.iter().any(|effect| { | ||||||
|                                 effect.name == SpellID::Recharge && effect.duration > 1 |                                 effect.name == SpellID::Recharge && effect.duration > 1 | ||||||
|                             }) { |                             }) { | ||||||
|                                 continue; |                                 leafs.push(leaf.use_spell(spell, false)); | ||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                     leafs.push(leaf.use_spell(spell)); |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             //leafs.iter().for_each(|leaf| println!("{:?}", leaf)); | ||||||
|         } |         } | ||||||
|  |         println!("leaf count: {}", leafs.len()); | ||||||
|  |         stats.0 = 0; | ||||||
|         for leaf in &leafs { |         for leaf in &leafs { | ||||||
|             if leaf.state == State::Win && leaf.spent_mana < smallest { |             if leaf.state == State::Win && leaf.spent_mana < smallest { | ||||||
|                 smallest = leaf.spent_mana; |                 smallest = leaf.spent_mana; | ||||||
|             } |             } | ||||||
|  |             match leaf.state { | ||||||
|  |                 State::Playing => stats.0 += 1, | ||||||
|  |                 State::Win => stats.1 += 1, | ||||||
|  |                 State::Loss => stats.2 += 1, | ||||||
|  |             }; | ||||||
|             //println!( |             //println!( | ||||||
|             //    "player hp: {}, boss hp: {}, spent mana so far: {}", |             //    "player hp: {}, boss hp: {}, spent mana so far: {}", | ||||||
|             //    leaf.player.hp, leaf.boss.hp, leaf.spent_mana |             //    leaf.player.hp, leaf.boss.hp, leaf.spent_mana | ||||||
|             //); |             //); | ||||||
|         } |         } | ||||||
|         leafs = leafs |         println!("Playing, win, loss: {stats:?}"); | ||||||
|             .clone() |         leafs.retain(|leaf| leaf.state == State::Playing && leaf.spent_mana < smallest); | ||||||
|             .iter() |  | ||||||
|             .filter(|&leaf| leaf.state == State::Playing || leaf.spent_mana <= smallest) |  | ||||||
|             .map(|leaf| leaf.to_owned()) |  | ||||||
|             .collect(); |  | ||||||
|         if leafs.is_empty() { |         if leafs.is_empty() { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         // already know it's higher than this |  | ||||||
|         if smallest <= 2000 { |  | ||||||
|             let mut count_losses = 0; |  | ||||||
|             for leaf in leafs { |  | ||||||
|                 if leaf.state == State::Loss { |  | ||||||
|                     count_losses += 1; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             println!("Losses: {count_losses}"); |  | ||||||
|             break; |  | ||||||
|         } |  | ||||||
|         test += 1; |  | ||||||
|         println!(" smallest: {smallest}"); |         println!(" smallest: {smallest}"); | ||||||
|     } |     } | ||||||
|     smallest |     smallest | ||||||
| } | } | ||||||
|  |  | ||||||
| pub fn process_part2(input: &str) -> u32 { | pub fn process_part2(input: &str) -> u32 { | ||||||
|     0 |     let mut boss = Character::default(); | ||||||
|  |     input.lines().for_each(|line| { | ||||||
|  |         let (attribute, value) = line.split_once(": ").unwrap(); | ||||||
|  |         if attribute == "Hit Points" { | ||||||
|  |             boss.hp = value.parse::<u32>().unwrap(); | ||||||
|  |         } else if attribute == "Damage" { | ||||||
|  |             boss.damage = value.parse::<u32>().unwrap(); | ||||||
|  |         } | ||||||
|  |     }); | ||||||
|  |     let player = Character { | ||||||
|  |         hp: 50, | ||||||
|  |         mana: 500, | ||||||
|  |         ..Default::default() | ||||||
|  |     }; | ||||||
|  |     // Initial state, nothing happened yet | ||||||
|  |     let start = RoundNode { | ||||||
|  |         player, | ||||||
|  |         boss, | ||||||
|  |         spent_mana: 0, | ||||||
|  |         state: State::Playing, | ||||||
|  |     }; | ||||||
|  |     let mut smallest = u32::MAX; | ||||||
|  |     let mut leafs = vec![start]; | ||||||
|  |     println!("start"); | ||||||
|  |     // Playing, Win, Loss | ||||||
|  |     let mut stats = (0, 0, 0); | ||||||
|  |     loop { | ||||||
|  |         let current_leafs = leafs.clone(); | ||||||
|  |         leafs.clear(); | ||||||
|  |         // create potential rounds | ||||||
|  |         for leaf in current_leafs { | ||||||
|  |             if leaf.state == State::Playing { | ||||||
|  |                 for spell in Spell::get_all() { | ||||||
|  |                     match spell.name { | ||||||
|  |                         SpellID::MagicMissile | SpellID::Drain => { | ||||||
|  |                             leafs.push(leaf.use_spell(spell, true)); | ||||||
|  |                         } | ||||||
|  |                         SpellID::Shield => { | ||||||
|  |                             if !leaf | ||||||
|  |                                 .player | ||||||
|  |                                 .status_effects | ||||||
|  |                                 .iter() | ||||||
|  |                                 .any(|effect| effect.name == SpellID::Shield && effect.duration > 1) | ||||||
|  |                             { | ||||||
|  |                                 leafs.push(leaf.use_spell(spell, true)); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         SpellID::Poison => { | ||||||
|  |                             if !leaf | ||||||
|  |                                 .boss | ||||||
|  |                                 .status_effects | ||||||
|  |                                 .iter() | ||||||
|  |                                 .any(|effect| effect.name == SpellID::Poison && effect.duration > 1) | ||||||
|  |                             { | ||||||
|  |                                 leafs.push(leaf.use_spell(spell, true)); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                         SpellID::Recharge => { | ||||||
|  |                             if !leaf.player.status_effects.iter().any(|effect| { | ||||||
|  |                                 effect.name == SpellID::Recharge && effect.duration > 1 | ||||||
|  |                             }) { | ||||||
|  |                                 leafs.push(leaf.use_spell(spell, true)); | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             //leafs.iter().for_each(|leaf| println!("{:?}", leaf)); | ||||||
|  |         } | ||||||
|  |         println!("leaf count: {}", leafs.len()); | ||||||
|  |         stats.0 = 0; | ||||||
|  |         for leaf in &leafs { | ||||||
|  |             if leaf.state == State::Win && leaf.spent_mana < smallest { | ||||||
|  |                 smallest = leaf.spent_mana; | ||||||
|  |             } | ||||||
|  |             match leaf.state { | ||||||
|  |                 State::Playing => stats.0 += 1, | ||||||
|  |                 State::Win => stats.1 += 1, | ||||||
|  |                 State::Loss => stats.2 += 1, | ||||||
|  |             }; | ||||||
|  |             //println!( | ||||||
|  |             //    "player hp: {}, boss hp: {}, spent mana so far: {}", | ||||||
|  |             //    leaf.player.hp, leaf.boss.hp, leaf.spent_mana | ||||||
|  |             //); | ||||||
|  |         } | ||||||
|  |         println!("Playing, win, loss: {stats:?}"); | ||||||
|  |         leafs.retain(|leaf| leaf.state == State::Playing && leaf.spent_mana < smallest); | ||||||
|  |         if leafs.is_empty() { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |         println!(" smallest: {smallest}"); | ||||||
|  |     } | ||||||
|  |     smallest | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Clone, PartialEq, Eq)] | #[derive(Debug, Clone, PartialEq, Eq)] | ||||||
| @@ -125,7 +208,7 @@ struct RoundNode { | |||||||
| } | } | ||||||
|  |  | ||||||
| impl RoundNode { | impl RoundNode { | ||||||
|     fn use_spell(&self, spell: Spell) -> RoundNode { |     fn use_spell(&self, spell: Spell, hard_mode: bool) -> RoundNode { | ||||||
|         if self.state != State::Playing { |         if self.state != State::Playing { | ||||||
|             eprintln!("State: {:#?}", self.state); |             eprintln!("State: {:#?}", self.state); | ||||||
|             eprintln!("spell: {spell:#?}"); |             eprintln!("spell: {spell:#?}"); | ||||||
| @@ -133,10 +216,25 @@ impl RoundNode { | |||||||
|         } |         } | ||||||
|         let mut player = self.player.clone(); |         let mut player = self.player.clone(); | ||||||
|         let mut boss = self.boss.clone(); |         let mut boss = self.boss.clone(); | ||||||
|  |         let mut recharge_actif = false; | ||||||
|  |         if hard_mode { | ||||||
|  |             player.hp -= 1; | ||||||
|  |         } | ||||||
|  |         if player.hp == 0 { | ||||||
|  |             return RoundNode { | ||||||
|  |                 player, | ||||||
|  |                 boss, | ||||||
|  |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|  |                 state: State::Loss, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|         // Player turn |         // Player turn | ||||||
|         for effect in player.status_effects.iter_mut() { |         for effect in player.status_effects.iter_mut() { | ||||||
|             if effect.name == SpellID::Recharge { |             if effect.name == SpellID::Recharge { | ||||||
|                 player.mana += effect.mana; |                 player.mana += effect.mana; | ||||||
|  |                 if effect.duration > 1 { | ||||||
|  |                     recharge_actif = true; | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|             effect.duration -= 1; |             effect.duration -= 1; | ||||||
|             if effect.duration > 0 && effect.name == SpellID::Shield { |             if effect.duration > 0 && effect.name == SpellID::Shield { | ||||||
| @@ -167,8 +265,15 @@ impl RoundNode { | |||||||
|             .into_iter() |             .into_iter() | ||||||
|             .filter(|&effect| effect.duration > 0) |             .filter(|&effect| effect.duration > 0) | ||||||
|             .collect::<Vec<Spell>>(); |             .collect::<Vec<Spell>>(); | ||||||
|         let used_mana = spell.cost; |  | ||||||
|         let mut dmg = 0; |         let mut dmg = 0; | ||||||
|  |         if player.mana < spell.cost { | ||||||
|  |             return RoundNode { | ||||||
|  |                 player, | ||||||
|  |                 boss, | ||||||
|  |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|  |                 state: State::Loss, | ||||||
|  |             }; | ||||||
|  |         } | ||||||
|         match spell.name { |         match spell.name { | ||||||
|             SpellID::MagicMissile => { |             SpellID::MagicMissile => { | ||||||
|                 player.mana = player.mana.saturating_sub(spell.cost); |                 player.mana = player.mana.saturating_sub(spell.cost); | ||||||
| @@ -198,15 +303,15 @@ impl RoundNode { | |||||||
|             return RoundNode { |             return RoundNode { | ||||||
|                 player, |                 player, | ||||||
|                 boss, |                 boss, | ||||||
|                 spent_mana: used_mana + self.spent_mana, |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|                 state: State::Win, |                 state: State::Win, | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|         if player.mana == 0 { |         if player.mana == 0 && !recharge_actif { | ||||||
|             return RoundNode { |             return RoundNode { | ||||||
|                 player, |                 player, | ||||||
|                 boss, |                 boss, | ||||||
|                 spent_mana: used_mana + self.spent_mana, |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|                 state: State::Loss, |                 state: State::Loss, | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
| @@ -236,7 +341,7 @@ impl RoundNode { | |||||||
|             return RoundNode { |             return RoundNode { | ||||||
|                 player, |                 player, | ||||||
|                 boss, |                 boss, | ||||||
|                 spent_mana: used_mana + self.spent_mana, |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|                 state: State::Win, |                 state: State::Win, | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
| @@ -252,14 +357,14 @@ impl RoundNode { | |||||||
|             return RoundNode { |             return RoundNode { | ||||||
|                 player, |                 player, | ||||||
|                 boss, |                 boss, | ||||||
|                 spent_mana: used_mana + self.spent_mana, |                 spent_mana: spell.cost + self.spent_mana, | ||||||
|                 state: State::Loss, |                 state: State::Loss, | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|         RoundNode { |         RoundNode { | ||||||
|             player, |             player, | ||||||
|             boss, |             boss, | ||||||
|             spent_mana: used_mana + self.spent_mana, |             spent_mana: spell.cost + self.spent_mana, | ||||||
|             state: State::Playing, |             state: State::Playing, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -401,17 +506,15 @@ mod tests { | |||||||
|         }; |         }; | ||||||
|         let mut smallest = u32::MAX; |         let mut smallest = u32::MAX; | ||||||
|         let mut leafs = vec![start]; |         let mut leafs = vec![start]; | ||||||
|         let mut test = 0; |  | ||||||
|         println!("start"); |         println!("start"); | ||||||
|         loop { |         loop { | ||||||
|             println!("iter: {test},"); |  | ||||||
|             let current_leafs = leafs.clone(); |             let current_leafs = leafs.clone(); | ||||||
|             leafs.clear(); |             leafs.clear(); | ||||||
|             // create potential rounds |             // create potential rounds | ||||||
|             for leaf in current_leafs { |             for leaf in current_leafs { | ||||||
|                 if leaf.state == State::Playing { |                 if leaf.state == State::Playing { | ||||||
|                     for spell in Spell::get_all() { |                     for spell in Spell::get_all() { | ||||||
|                         leafs.push(leaf.use_spell(spell)); |                         leafs.push(leaf.use_spell(spell, false)); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -423,15 +526,14 @@ mod tests { | |||||||
|                 if leaf.state == State::Playing { |                 if leaf.state == State::Playing { | ||||||
|                     all_done = false; |                     all_done = false; | ||||||
|                 } |                 } | ||||||
|                 println!( |                 //println!( | ||||||
|                     "player hp: {}, boss hp: {}, spent mana so far: {}", |                 //    "player hp: {}, boss hp: {}, spent mana so far: {}", | ||||||
|                     leaf.player.hp, leaf.boss.hp, leaf.spent_mana |                 //    leaf.player.hp, leaf.boss.hp, leaf.spent_mana | ||||||
|                 ); |                 //); | ||||||
|             } |             } | ||||||
|             if all_done { |             if all_done { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             test += 1; |  | ||||||
|             println!(" smallest: {smallest}"); |             println!(" smallest: {smallest}"); | ||||||
|         } |         } | ||||||
|         assert_eq!(smallest, 226); |         assert_eq!(smallest, 226); | ||||||
| @@ -458,17 +560,15 @@ mod tests { | |||||||
|         }; |         }; | ||||||
|         let mut smallest = u32::MAX; |         let mut smallest = u32::MAX; | ||||||
|         let mut leafs = vec![start]; |         let mut leafs = vec![start]; | ||||||
|         let mut test = 0; |  | ||||||
|         println!("start"); |         println!("start"); | ||||||
|         loop { |         loop { | ||||||
|             println!("iter: {test},"); |  | ||||||
|             let current_leafs = leafs.clone(); |             let current_leafs = leafs.clone(); | ||||||
|             leafs.clear(); |             leafs.clear(); | ||||||
|             // create potential rounds |             // create potential rounds | ||||||
|             for leaf in current_leafs { |             for leaf in current_leafs { | ||||||
|                 if leaf.state == State::Playing { |                 if leaf.state == State::Playing { | ||||||
|                     for spell in Spell::get_all() { |                     for spell in Spell::get_all() { | ||||||
|                         leafs.push(leaf.use_spell(spell)); |                         leafs.push(leaf.use_spell(spell, false)); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -480,20 +580,34 @@ mod tests { | |||||||
|                 if leaf.state == State::Playing { |                 if leaf.state == State::Playing { | ||||||
|                     all_done = false; |                     all_done = false; | ||||||
|                 } |                 } | ||||||
|                 println!( |                 //println!( | ||||||
|                     "player hp: {}, boss hp: {}, spent mana so far: {}", |                 //    "player hp: {}, boss hp: {}, spent mana so far: {}", | ||||||
|                     leaf.player.hp, leaf.boss.hp, leaf.spent_mana |                 //    leaf.player.hp, leaf.boss.hp, leaf.spent_mana | ||||||
|                 ); |                 //); | ||||||
|             } |             } | ||||||
|             if all_done { |             if all_done { | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
|             test += 1; |  | ||||||
|             println!(" smallest: {smallest}"); |             println!(" smallest: {smallest}"); | ||||||
|         } |         } | ||||||
|         assert_eq!(smallest, 641); |         assert_eq!(smallest, 641); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     #[allow(dead_code)] | ||||||
|  |     fn init_characters() -> (Character, Character) { | ||||||
|  |         let player = Character { | ||||||
|  |             hp: 50, | ||||||
|  |             mana: 500, | ||||||
|  |             ..Default::default() | ||||||
|  |         }; | ||||||
|  |         let boss = Character { | ||||||
|  |             hp: 14, | ||||||
|  |             damage: 8, | ||||||
|  |             ..Default::default() | ||||||
|  |         }; | ||||||
|  |         (player, boss) | ||||||
|  |     } | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn part2() { |     fn part2() { | ||||||
|         let result = process_part2(""); |         let result = process_part2(""); | ||||||
|   | |||||||
							
								
								
									
										155
									
								
								y2015/src/days/d23.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								y2015/src/days/d23.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,155 @@ | |||||||
|  | use core::panic; | ||||||
|  |  | ||||||
|  | pub fn process_part1(input: &str) -> (i32, i32) { | ||||||
|  |     let mut a = 0; | ||||||
|  |     let mut b = 0; | ||||||
|  |     let instructions = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| line.to_string()) | ||||||
|  |         .collect::<Vec<String>>(); | ||||||
|  |     let mut idx: i32 = 0; | ||||||
|  |     loop { | ||||||
|  |         if let Some(instruction) = instructions.get(idx as usize) { | ||||||
|  |             let (instruction_name, instruction_action) = instruction.split_once(" ").unwrap(); | ||||||
|  |             match instruction_name { | ||||||
|  |                 "hlf" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a /= 2; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b /= 2; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "tpl" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a *= 3; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b *= 3; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "inc" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a += 1; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b += 1; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "jmp" => { | ||||||
|  |                     let offset = instruction_action.parse::<i32>().unwrap(); | ||||||
|  |                     idx += offset; | ||||||
|  |                 } | ||||||
|  |                 "jie" => { | ||||||
|  |                     let (reg, offset) = instruction_action.split_once(", ").unwrap(); | ||||||
|  |                     let offset: i32 = offset.parse().unwrap(); | ||||||
|  |                     if (reg == "a" && a % 2 == 0) || (reg == "b" && b % 2 == 0) { | ||||||
|  |                         idx += offset; | ||||||
|  |                     } else { | ||||||
|  |                         idx += 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 "jio" => { | ||||||
|  |                     let (reg, offset) = instruction_action.split_once(", ").unwrap(); | ||||||
|  |                     let offset: i32 = offset.parse().unwrap(); | ||||||
|  |                     if (reg == "a" && a == 1) || (reg == "b" && b == 1) { | ||||||
|  |                         idx += offset; | ||||||
|  |                     } else { | ||||||
|  |                         idx += 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 _ => panic!("Unknown instruction {instruction_name}"), | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             return (a, b); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part2(input: &str) -> (i32, i32) { | ||||||
|  |     let mut a = 1; | ||||||
|  |     let mut b = 0; | ||||||
|  |     let instructions = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| line.to_string()) | ||||||
|  |         .collect::<Vec<String>>(); | ||||||
|  |     let mut idx: i32 = 0; | ||||||
|  |     loop { | ||||||
|  |         if let Some(instruction) = instructions.get(idx as usize) { | ||||||
|  |             let (instruction_name, instruction_action) = instruction.split_once(" ").unwrap(); | ||||||
|  |             match instruction_name { | ||||||
|  |                 "hlf" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a /= 2; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b /= 2; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "tpl" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a *= 3; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b *= 3; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "inc" => { | ||||||
|  |                     if instruction_action == "a" { | ||||||
|  |                         a += 1; | ||||||
|  |                     } else if instruction_action == "b" { | ||||||
|  |                         b += 1; | ||||||
|  |                     } | ||||||
|  |                     idx += 1; | ||||||
|  |                 } | ||||||
|  |                 "jmp" => { | ||||||
|  |                     let offset = instruction_action.parse::<i32>().unwrap(); | ||||||
|  |                     idx += offset; | ||||||
|  |                 } | ||||||
|  |                 "jie" => { | ||||||
|  |                     let (reg, offset) = instruction_action.split_once(", ").unwrap(); | ||||||
|  |                     let offset: i32 = offset.parse().unwrap(); | ||||||
|  |                     if (reg == "a" && a % 2 == 0) || (reg == "b" && b % 2 == 0) { | ||||||
|  |                         idx += offset; | ||||||
|  |                     } else { | ||||||
|  |                         idx += 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 "jio" => { | ||||||
|  |                     let (reg, offset) = instruction_action.split_once(", ").unwrap(); | ||||||
|  |                     let offset: i32 = offset.parse().unwrap(); | ||||||
|  |                     if (reg == "a" && a == 1) || (reg == "b" && b == 1) { | ||||||
|  |                         idx += offset; | ||||||
|  |                     } else { | ||||||
|  |                         idx += 1; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 _ => panic!("Unknown instruction {instruction_name}"), | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             return (a, b); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     const INPUT: &str = "inc a | ||||||
|  | jio a, +2 | ||||||
|  | tpl a | ||||||
|  | inc a"; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(INPUT); | ||||||
|  |         assert_eq!(result.0, 2); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part2() { | ||||||
|  |         let result = process_part2(INPUT); | ||||||
|  |         assert_eq!(result.0, 7); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										106
									
								
								y2015/src/days/d24.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								y2015/src/days/d24.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | |||||||
|  | use itertools::Itertools; | ||||||
|  |  | ||||||
|  | #[derive(Clone, Debug, Default)] | ||||||
|  | struct Group { | ||||||
|  |     packages: Vec<usize>, | ||||||
|  |     weight: usize, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Group { | ||||||
|  |     fn new(packages: Vec<usize>) -> Self { | ||||||
|  |         let mut group = Self::default(); | ||||||
|  |         for package in packages { | ||||||
|  |             group.add(package); | ||||||
|  |         } | ||||||
|  |         group | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn add(&mut self, package: usize) { | ||||||
|  |         self.packages.push(package); | ||||||
|  |         self.weight += package; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn qe(&self) -> usize { | ||||||
|  |         self.packages.iter().product() | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     fn len(&self) -> usize { | ||||||
|  |         self.packages.len() | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part1(input: &str) -> usize { | ||||||
|  |     let packages = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| line.parse::<usize>().unwrap()) | ||||||
|  |         .collect::<Vec<usize>>(); | ||||||
|  |     let group_weight = packages.iter().sum::<usize>() / 3; | ||||||
|  |     let mut best_group = (usize::MAX, usize::MAX); | ||||||
|  |     for k in 1..packages.len() { | ||||||
|  |         let combinations = packages.clone().into_iter().combinations(k); | ||||||
|  |         for combination in combinations { | ||||||
|  |             let group = Group::new(combination.clone()); | ||||||
|  |             if group.weight == group_weight { | ||||||
|  |                 if group.len() < best_group.0 { | ||||||
|  |                     best_group = (group.len(), group.qe()); | ||||||
|  |                 } | ||||||
|  |                 if group.len() == best_group.0 && group.qe() < best_group.1 { | ||||||
|  |                     best_group = (group.len(), group.qe()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     best_group.1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part2(input: &str) -> usize { | ||||||
|  |     let packages = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| line.parse::<usize>().unwrap()) | ||||||
|  |         .collect::<Vec<usize>>(); | ||||||
|  |     let group_weight = packages.iter().sum::<usize>() / 4; | ||||||
|  |     let mut best_group = (usize::MAX, usize::MAX); | ||||||
|  |     for k in 1..packages.len() { | ||||||
|  |         let combinations = packages.clone().into_iter().combinations(k); | ||||||
|  |         for combination in combinations { | ||||||
|  |             let group = Group::new(combination.clone()); | ||||||
|  |             if group.weight == group_weight { | ||||||
|  |                 if group.len() < best_group.0 { | ||||||
|  |                     best_group = (group.len(), group.qe()); | ||||||
|  |                 } | ||||||
|  |                 if group.len() == best_group.0 && group.qe() < best_group.1 { | ||||||
|  |                     best_group = (group.len(), group.qe()); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     best_group.1 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     const INPUT: &str = "1 | ||||||
|  | 2 | ||||||
|  | 3 | ||||||
|  | 4 | ||||||
|  | 5 | ||||||
|  | 7 | ||||||
|  | 8 | ||||||
|  | 9 | ||||||
|  | 10 | ||||||
|  | 11"; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(INPUT); | ||||||
|  |         assert_eq!(result, 99); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part2() { | ||||||
|  |         let result = process_part2(INPUT); | ||||||
|  |         assert_eq!(result, 44); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								y2015/src/days/d25.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								y2015/src/days/d25.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | use utils::number::Number; | ||||||
|  |  | ||||||
|  | // 31562160 too high | ||||||
|  | pub fn process_part1(x: u32, y: u32) -> Number { | ||||||
|  |     // the grid is actually a pyramid | ||||||
|  |     //   1 | ||||||
|  |     //  2 3 | ||||||
|  |     // 4 5 6 | ||||||
|  |     // etc | ||||||
|  |     // Num on top == 20151125 | ||||||
|  |     let mut current = Number::from(20151125); | ||||||
|  |     let mut starting_y_idx = 2; | ||||||
|  |     loop { | ||||||
|  |         let mut x_idx = 1; | ||||||
|  |         for y_idx in (1..=starting_y_idx).rev() { | ||||||
|  |             current *= Number::from(252533); | ||||||
|  |             current %= Number::from(33554393); | ||||||
|  |             if x_idx == x && y_idx == y { | ||||||
|  |                 return current; | ||||||
|  |             } | ||||||
|  |             x_idx += 1; | ||||||
|  |         } | ||||||
|  |         starting_y_idx += 1; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(6, 6); | ||||||
|  |         assert_eq!(result, 27995004.into()); | ||||||
|  |         let result = process_part1(1, 2); | ||||||
|  |         assert_eq!(result, 31916031.into()); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -8,7 +8,14 @@ pub mod d15; | |||||||
| pub mod d16; | pub mod d16; | ||||||
| pub mod d17; | pub mod d17; | ||||||
| pub mod d18; | pub mod d18; | ||||||
|  | pub mod d19; | ||||||
| pub mod d2; | pub mod d2; | ||||||
|  | pub mod d20; | ||||||
|  | pub mod d21; | ||||||
|  | pub mod d22; | ||||||
|  | pub mod d23; | ||||||
|  | pub mod d24; | ||||||
|  | pub mod d25; | ||||||
| pub mod d3; | pub mod d3; | ||||||
| pub mod d4; | pub mod d4; | ||||||
| pub mod d5; | pub mod d5; | ||||||
| @@ -16,11 +23,3 @@ pub mod d6; | |||||||
| pub mod d7; | pub mod d7; | ||||||
| pub mod d8; | pub mod d8; | ||||||
| pub mod d9; | pub mod d9; | ||||||
|  |  | ||||||
| pub mod d19; |  | ||||||
|  |  | ||||||
| pub mod d20; |  | ||||||
|  |  | ||||||
| pub mod d21; |  | ||||||
|  |  | ||||||
| pub mod d22; |  | ||||||
|   | |||||||
							
								
								
									
										1
									
								
								y2016/resources/1_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								y2016/resources/1_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | L5, R1, L5, L1, R5, R1, R1, L4, L1, L3, R2, R4, L4, L1, L1, R2, R4, R3, L1, R4, L4, L5, L4, R4, L5, R1, R5, L2, R1, R3, L2, L4, L4, R1, L192, R5, R1, R4, L5, L4, R5, L1, L1, R48, R5, R5, L2, R4, R4, R1, R3, L1, L4, L5, R1, L4, L2, L5, R5, L2, R74, R4, L1, R188, R5, L4, L2, R5, R2, L4, R4, R3, R3, R2, R1, L3, L2, L5, L5, L2, L1, R1, R5, R4, L3, R5, L1, L3, R4, L1, L3, L2, R1, R3, R2, R5, L3, L1, L1, R5, L4, L5, R5, R2, L5, R2, L1, L5, L3, L5, L5, L1, R1, L4, L3, L1, R2, R5, L1, L3, R4, R5, L4, L1, R5, L1, R5, R5, R5, R2, R1, R2, L5, L5, L5, R4, L5, L4, L4, R5, L2, R1, R5, L1, L5, R4, L3, R4, L2, R3, R3, R3, L2, L2, L2, L1, L4, R3, L4, L2, R2, R5, L1, R2 | ||||||
							
								
								
									
										20
									
								
								y2016/src/bin/d1.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								y2016/src/bin/d1.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | use std::fs; | ||||||
|  |  | ||||||
|  | use y2016::days::d1; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  |     part2(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/1_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d1::process_part1(&content)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part2() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/1_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d1::process_part2(&content)); | ||||||
|  | } | ||||||
							
								
								
									
										105
									
								
								y2016/src/days/d1.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								y2016/src/days/d1.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | |||||||
|  | use core::panic; | ||||||
|  | use std::collections::{HashMap, HashSet}; | ||||||
|  |  | ||||||
|  | #[derive(Clone, Copy, Hash, PartialEq, Eq)] | ||||||
|  | enum Orientation { | ||||||
|  |     North, | ||||||
|  |     East, | ||||||
|  |     South, | ||||||
|  |     West, | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Orientation { | ||||||
|  |     fn turn(&mut self, direction: &str) { | ||||||
|  |         match direction { | ||||||
|  |             "R" => match self { | ||||||
|  |                 Orientation::North => *self = Self::East, | ||||||
|  |                 Orientation::East => *self = Self::South, | ||||||
|  |                 Orientation::South => *self = Self::West, | ||||||
|  |                 Orientation::West => *self = Self::North, | ||||||
|  |             }, | ||||||
|  |             "L" => match self { | ||||||
|  |                 Orientation::North => *self = Self::West, | ||||||
|  |                 Orientation::West => *self = Self::South, | ||||||
|  |                 Orientation::South => *self = Self::East, | ||||||
|  |                 Orientation::East => *self = Self::North, | ||||||
|  |             }, | ||||||
|  |             _ => panic!("Wrong direction. Only R and L allowed"), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part1(input: &str) -> i32 { | ||||||
|  |     let mut orientation = Orientation::North; | ||||||
|  |     let mut movements = HashMap::new(); | ||||||
|  |     let mut input = input.to_string(); | ||||||
|  |     input.pop(); | ||||||
|  |     for movement in input.split(", ") { | ||||||
|  |         let (direction, blocks) = movement.split_at(1); | ||||||
|  |         orientation.turn(direction); | ||||||
|  |         let blocks = blocks.parse::<i32>().unwrap(); | ||||||
|  |         movements | ||||||
|  |             .entry(orientation) | ||||||
|  |             .and_modify(|distance| *distance += blocks) | ||||||
|  |             .or_insert(blocks); | ||||||
|  |     } | ||||||
|  |     let up = movements.get(&Orientation::North).unwrap_or(&0); | ||||||
|  |     let down = movements.get(&Orientation::South).unwrap_or(&0); | ||||||
|  |     let left = movements.get(&Orientation::West).unwrap_or(&0); | ||||||
|  |     let right = movements.get(&Orientation::East).unwrap_or(&0); | ||||||
|  |     (up - down).abs() + (left - right).abs() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part2(input: &str) -> i32 { | ||||||
|  |     let mut orientation = Orientation::North; | ||||||
|  |     let mut visited_coords = HashSet::new(); | ||||||
|  |     let mut horizontal: i32 = 0; | ||||||
|  |     let mut vertical: i32 = 0; | ||||||
|  |     let mut input = input.to_string(); | ||||||
|  |     input.pop(); | ||||||
|  |     for movement in input.split(", ") { | ||||||
|  |         let (direction, blocks) = movement.split_at(1); | ||||||
|  |         orientation.turn(direction); | ||||||
|  |         let blocks = blocks.parse::<i32>().unwrap(); | ||||||
|  |         for _block in 1..=blocks { | ||||||
|  |             match orientation { | ||||||
|  |                 Orientation::North => vertical += 1, | ||||||
|  |                 Orientation::South => vertical -= 1, | ||||||
|  |                 Orientation::East => horizontal += 1, | ||||||
|  |                 Orientation::West => horizontal -= 1, | ||||||
|  |             } | ||||||
|  |             if visited_coords.contains(&(horizontal, vertical)) { | ||||||
|  |                 return horizontal.abs() + vertical.abs(); | ||||||
|  |             } else { | ||||||
|  |                 visited_coords.insert((horizontal, vertical)); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     panic!("Did not find easter bunny hq"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     const INPUT1: &str = "R2, L3 "; | ||||||
|  |     const INPUT2: &str = "R2, R2, R2 "; | ||||||
|  |     const INPUT3: &str = "R5, L5, R5, R3 "; | ||||||
|  |     const INPUT4: &str = "R8, R4, R4, R8 "; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(INPUT1); | ||||||
|  |         assert_eq!(result, 5); | ||||||
|  |         let result = process_part1(INPUT2); | ||||||
|  |         assert_eq!(result, 2); | ||||||
|  |         let result = process_part1(INPUT3); | ||||||
|  |         assert_eq!(result, 12); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part2() { | ||||||
|  |         let result = process_part2(INPUT4); | ||||||
|  |         assert_eq!(result, 4); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										1
									
								
								y2016/src/days/mod.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								y2016/src/days/mod.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | pub mod d1; | ||||||
| @@ -1 +1 @@ | |||||||
|  | pub mod days; | ||||||
|   | |||||||
| @@ -4,3 +4,5 @@ version = "0.1.0" | |||||||
| edition = "2021" | edition = "2021" | ||||||
|  |  | ||||||
| [dependencies] | [dependencies] | ||||||
|  | regex = "1.11.1" | ||||||
|  | utils = { workspace = true } | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								y2024/resources/3_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								y2024/resources/3_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | $  mul(402,190))&<why(211,617)how()/;mul(506,313)[^^<!$#when(636,198),]mul(744,268)#&!what()&!;mul(631,641)where()@select()!@?(:;how()mul(25,288)&~^select()mul(683,657)'mul(505,315)+~:-mul(671,741)]{mul(397,54))?mul(511,935)where()select()where()-mul(525,623)mul(206,770){/}don't()from()mul(260,967)-how() -/[^(mul(500,994)!:mul(391,833)#)>who(),where(376,378)why();$mul(394,346)%:]^from()>:mul(130,944)who()>where()select()}:mul(952,439)?/how()from()^$why()do()@*{mul(557,916)&(who()mul(445,933):(,;>?mul(108,268)don't()select(574,441)-mul(132,870)from(){mul(441,660)why(),from();mul(919,820):#/%)why()*mul(194,790);#/^#select()?mul(981,514)$what(796,873)when() %from()mul(164,772):&:select()@mul(396,80)select()what()%),) mul(213,928){?who();@@mul(320,229)where(348,623)*when()when(180,565)mul(214,912)!mul(848,738)from()+):^how()-&[mul(378,433)select():%~mul(696,421)mul(364,341)?^don't()*&mul(89,441)how()select()what(),select()mul(423,822),?&(how()']what())$mul(21,844)&,select()/>^)'mul(469,230))when()where()*,#mul(569,594)why()what():{ select(200,250){())mul(661,628)#)why()from(325,19)who() mul(758,985){%&where()!how(213,616)*mul(394,768)mul(831,12)*where()>who(986,151)mul(962,504)$:<!)where()%$&when()mul(900,577)<>^[>;mul(948,363)$@;]mul(857,273) how() ,:!select(),[mul(31,766)} *mul(372,138)+,#!~(>;%mul(774,958)#}&+why()*when()mul(560,137)}mul(72,718)when()^{]':{how()/mul(985,120)@*[do()$how()mul(891,69)select()mul(546,834)@$mul(767,879)$$!/&why()?mul(876,495){^/&)who()<~]mul(911,71){?#mul(116,462);:%<^'?}~why()mul(258,286)from()^#^?how()&who()mul(97,540)select()who()do(){^~~<why(955,532)@[ how()mul(682,75)~){?where()<mul(63,26)-where()^ <^mul(336,475)&when()mul(637,386)+*when()<^]mul(846,915)!mul(795,805)$what()[~#*@:/@mul(370,651)?$select()^how()}!mul(705,839)~*;%!^+why()do()!:)[#{mul(112,21)*mul(285,252)mul(451,396){&> )'mul(57,589)when()**mul(554,575)*+^mul(856,360)mul(530,200)@/&}*where()mul(588,2)who()$]mul(604,72)who()}from(524,212)mul(250,680)<;@;@how()?#mul(555,956)%(;:+<{(who()select()mul(377,822)+when()@[&{&from();*mul(457,538)mul(52,298)who()%when()%who()how()from(9,264)mul(452,941)where()+?,-don't()when()select()<mul(956,185)^}don't(){$/~how()][ #)mul(717,593,when(64,768):what()%(mul(922,407)#why(646,569)$(~:{#mul(3,438)+/#<*select())how()don't()!where();mul(853,725)%?}/!from()<?*mul!+>$''mul(229,512){{from()what()?!'^select()mul(185,787)<*mul(688,834)  @@what(),}select()>mul(825,27))~&!;mul(796,378)*+(-select(); mul!):{!;who()$how()why()don't()select()how(451,129)]#*^mul(852,354)[mul(596,889)mul(476,207):#what()-+mul(467,323) from()why()}(}^&:mul(955,498)]{;mul(797,177)mul(321,350):mul(784,667)mul(707,927)~%#why()why()what();mul(515,511)from(589,691)mul*&[mul(884,558)/mul(824,926))+from(331,316)where()!*!:mul(938,881)]mul(287,358what()@from(226,364)+:^)-when(361,935)select()mul(324,887)@where()select())(mul(430>&][mul(381,417)}*why()why()!*#~mul(729,14)>%what()'where(){}mul(483,820)when(206,921)&when()@how()mul(608,185)how(5,376)%mul(150,182)><when()@:@mul(953,86)mul(332,881)*mul(688,895)^<select()!%<+mul(5,990)>]/!( (+mul(78,588)what()@ why()when()*+from();;mul(837,417)who()mul(786,516)'how()%:~;%]who()<mul(576,960),@why()<<+'mul(160,572)*why()where()-when(353,689){[;mul(634,920)mul(482,207)( (when()<>:;-mul(917,130) | ||||||
|  | why();[what()(,]mul(177,501)mul(346,27)when(428,856)who(){how()mul(513,432)what()']&where(),>?select(),do()+how()![where()mul(399,972)mul(862,828)when()?^&)mul(200,579)how()who()mul(79,535) <don't()<mul(450,265@/!mul(332,269)/select()why()-mul(436,976)&;$#-;^)what(878,202)mul(114,418}-~<! ,who()mul(394,75)<from()mul(51,262)from()#what()^*don't()%mul(133,6)mul(63,773)$%; ';@^what()!mul(142,703)where(178,667)}/(don't()how()mul(451,569)-~mul(395,265)+@>{select(684,626)){where()?)mul(52,852)&< @what()^what()]mul(807,491)&#@mul(130,14)<what()who():@mul(195,735)]when()<how()where()$,how()where()mul(310,933);[<$)mul(479,998),from()/where()@mul(583,819);select()}+$when()*mul(100,443)/$)mul(300,699)select()# #what()?:(^mul(824,627)#>mul(884,328)when()%who(255,459)mul(434,697)?how(),,*)#mul(522,208) !&/mul(296,945)-~!what()when(),,%mul(127[mul(637,905)~from()/where()/where()mul(375,117)(<;select()how():!^{mul(856from()][from()}&when(331,921)mul(873,410)'@/mul(777,739>when()!^!)mul(460,138)!'{why()<~/<mul(820,107)/<(*;& mul(887,760)/mul(701,198)+@@,{ where():mul(108,795)why()]#&don't()#+where()mul(491,644)mul(148,474)!mul(216,458)<,when()[(#mul(205^from()]@(where()?@mul(808,178)!@from();~%:]})mul(807,17)>when()when()+:(what()@)mul(97,8)mul(324,169)select()mul(396,755)!#select()^&#];when()don't()$where()/^{~{how()mul(856,118)$*who()who()#when()mul(683,431)/mul(946,398)mul(902,742)(mul(448,592)'mul(750,527)]/mul(98,232*,select()(!~/<{mul(104,754)^mul(959,509) '$~@/do()when(642,16);what() <#(+!mul(564,313)$]'mul(945from()*]!who()[%who()'*#don't()<![select()where(387,153)mul(283,666)mul(323,423)what()}where(552,799)@#what()mul(897,782)&why();where()[$#!select(){mul(965,10)?$mul(515,710)why(),!?*:mul(442,335)&<who(526,485)who()!)when():%>mul(410,907)@what()select()select()?mul(21,969)mul(942,472)' what() ?select()why()^do() /$-who()::mul(36,303)~mul(783,530)'$what()$:%?mul(74,743);~^;>do()who()who()>}mul(391@^mul(681,793)where()%!-,mul(171,461)![<<&don't()+mul(707,127)^?mul(641,578)where()how()what()what(89,960)}(]mul(431,871)mul,+mul(610,323)<why()what()mul(343,108)'mul(902,793)[where(661,90)#who())?#![}mul(535,881)mul(782,524)select()>why()why()mul(662,436)'&[^mul(397%from()>*why()%-mul(186,254)?*]!who()!select(839,279)<mul(518,739)}from()don't()(where()how()} who()~mul(394,539)^why()where()+?from()(mul(32,988)]mul(459,826)};mul(95,871)?&{select()&/;mul(626,919) '++{;from()mul(161,733),#%mul(662,339)* +mul(246,943)where()#what()what(){+,;,who()mul(555,251)what()what()%(mul(374,548)>]+select()mul(84,228)[mul(536,784)where()+*how()mul(893,249;what()(mul(917,825)mul&mul(891,755))${,#@@mul(511,464)what()where()'when()mul:who()mul(730,485)][,mul(592,512)[why(52,524),*]@select()(mul(829})' *~- [)mul(111,611)how(838,283)+#{>when()?who(764,939)from()mul(925,978)[*#who(182,485)how()select()mul(538,803)>&where()how()$what() }{mul(671,684)/why(106,337)+<#(mul(453,150)++[--from(475,981)where()&{mul(197,568) &;/mulwhy()~(@*who()/!#mul(466,89)'why(594,849)(select()( mul(30,648)what()from()(select()mul(829,947)mul(903,174),-,@select()from()select()mul(462,421)&when()!when()^%;),mul(631,703)mul(917,971)mul(473,892) don't(){/~>,why()[*mul(800,49)when()why()>%)*who())]mul(571,734)<(mul(283,803)~mul(752,111)why(); %<,(where()'&mul(393,613)mul(257,15)&mul(14,159)]mul(502,324)what()how()when(294,303)-%:when()mul(542,760)>}why(),how()mul(726,492)mul(169,827)^: ^~[ mul(859how()#how()))%@mul(564,652) mul(403,8)~mul(507,846) | ||||||
|  | !!{[){mul(470,989)#mul(58,989+who()?*{! [mul(498,119)%~{mul(206,173)who()from()how()}%^*;how()@mul(154,721){~mul(451,125)<-mul(386,969)!<:mul(890,369)!*{+]-,where()when()when()mul(657,994)]why():mul(898,340) how()(#who()<mul(352,838)[%)who()?how():&when(173,843)mul(21,663)how()&]^}-^>where()mul(502,23) mul(681,55$( ,mul(807,634)&${what()~what()mul(176,10)'(what()why()@~]mul(564,162)!%select()mul(526,996)!-mul(993,991)/'!?mul(118,854)?~-?mul(74,965)who())-({when()select()]mul(913,115)/[who()where()when()<%!mul, ]~#/ mul(990,573)&from()^}%$mul(226,132)mul(431,657)[who())where(690,880)',- ,mul(21,346)what()how(298,600)-mul(174,190)mul(755,197)who(){>&$what()from(853,522)mul(560,222)what()$when()[mul(933)from(881,714)[when()#~(]{mul(67,261)!mul(775,385)don't()[who()how() where()/mul(381,343)do()<}$%;<>how()'mul(460,761)(mul(83,660)[where()mul(539,808'&select()*don't()(mul(274,997)mul(274,981)}/#who()[]mul(414,738){$do()&<?:what()&why()%who()mul(638,411)&[?don't()when()+ ?> mul(672,195)'}<<mul(772,21)>@[&;select()mul(90,631) $*mul(869,108)^$+:([&#!mul(801when()~}mul(827,339)who(851,624)%&why()'when()'mul(586,599)+:'/>when()[!mul(139,133)*'!$){#~?mul(565,566)mul(618,83)+mul(765,263)why()/+how()#'{how(521,404) !mul(344,377)/select(536,767)@why()-why()'where()why(468,917)mul(302,909){:mul(632,525)from()>who()(@who()mul(383,809)<>select();when();select()who()?<do()$*mul(597,59)when()/(}mul(79,440)$mul(565,850){[how()where()mul(368,953):*}from();!,-mul(767,182)what()from()$why()when()%/&mul(410,122)%!-mul(246,726)$when()%mul(343,179) {-?why()mul(816,33),:;%#;$mul(340,519(mul(858,204)select()@!:mul(739,205)why();*]/'select()mul(891,670)]why(5,493)how()[?when(519,92)when()mul(790,933)/**>'>where()select()mul(142,6)*:(>'mul(963,13),don't() how()when()/'*mul(18,872)'mul(465,102)(#+mul(590,510! from()mul(133,919)}[,from()from() (mul(820,448)[mul(442,548)mul(977,871)}who()+select()who()mul(606,74)^:)mul>!mul(129,889)/+mul(310,726)who()from()*what()mul(49,487)/)where()]:mul(615,825)}}don't()mul(266,421)}don't()(how();select(908,869)+how()where()mul(56,163)mul(288,896)mul(872^mul(391,531)$mul(152,112)'^,from()mul(889,862)mul(562,569)^ *{';when()!(mul(236,30)>]-why()]what(83,46)when()/>how()mul(634,71)?,?{^?mul(438,21)what()mul(993,470){<[when()where()from()mul(190,720)/%where()@mul(339,904why()where()mul(123,502);) /mul(178,842)how()mul(737,234) !mul(985,241)**?~-mul(349,197)<[mul(22,535)&(&why()mul(460,416)when()&do()[how()when(), mul(250,415how()@-%*:who()*mul(181,581):@mul(353,992)*when()what()mul(247,102)where()?why(607,695)#don't()?when()from()%@<mul(624,872)+select()-^mul(589,215)mul(626,138)mul(726,746)>)from()where()mul(738,410)!where(808,172),;:*'mul/^(#mul(545,174)^:when()-$^'mul(670,694(why(117,443):mul(12,180);'@what()mul(314,309)mul(790,161)&what()where(620,466)&who()[-]*where()mul(147,178)why()^][}'~$mul(441,381){ mul(138,111)<+) <mul(795,46)mul(207,817)why()mul(360,197)?,,where()!$select()mul(908,513)'when()*&,~{:don't()mul(976,931)}$]/select()@>what()[mul(842,241):(from()how()$:mul(329,926)don't()-@$-from(245,221)]+mul(161,472):/how()mul(178,909)mul(729,950)>]mul(310,170)mul(868,180)}mul(685,89)}what(690,794)!who()!mul(670,698']>~mul(464,132)-when(827,257)?)when()#/?when()#!/usr/bin/perlfrom()--{where())what()(mul(54,26) | ||||||
|  | @)+mul(601,827)from()how()]'how()[where()how()]]mul(943,407)what()/why()}}mul(516,728)<-+ why() ?'mul(651,195)who(472,480)select()^{}/]mul(159,449)#{select()]>why(457,182)mul(889,383)mul(717,768)~>{select()from()~@{>'mul(25,532#}who())mul(582,481)where()>$?) !mul(232,573)mul(27,868)^~from()#where()do()how()>mul(24,375)'!;,,mul(34,942)?-mul(511,814)<:{{how()}{what()mul(369,392)mul(643,828)mul(12,913)from()~select(){ +$$mul(384,257){who()!{$ )#/!mul(607,455)how()*(( /-+::mul(747,552)mul(333,364)how()*?select(914,438)% ~,mul(257,957)do()where(){+#mul(85,930)when()^'<~^/ mul(538,737)?,%what()*-^ where()mul(959,252)mul(435,422)#where()mulwhere()mul(634,612),}{select(863,784){[do()who()}*+mul(842,759),#what());[}why(616,35)%mul(631,814);where()/)mul(768,481)>{!)>who()who()select()how()mul(432,507)&)!>{%>(mul:$?(?~@ }mul(60,211)what()what()*what()when()+];mul(960,9)- ~'mul(678]+&!mul(252,399)what()?:?} !@>[mul(510,368)mul(674,905)how()/why()^mul(763,579)mul(771,675)mul(565,944)'who(345,580)#<where(248,141)from()don't()when()who()#from()>~<mul(708,226)$select(856,127),[mul(669,13)mul(228,509)} why()mul(665,556)<]$:])@^<when()mul(820,340) mul(430,345)from()who()<why()#>!who()mul(349,192)[mul(673@#+/mul(623,920)&^where()}#who()mul(331from()$'+from()mul(906,455)select()mul(969,326)where()[$(how()[/;/-mul(342,396)>how()[*mul(319,806)~#mul(374,571)who()mul(767,564)%:-[-;@)mul(724,513)%{[$~mul(559,103)mul(495,144)who()<<why()who();)~mul(966,554)+[]select()>mul(485,851)(mul(935,69)from()mul(745,465)select();/^mul(788,539)}:/+from()select()^/~mul(385,82)mul(939,676)#!%how(){who()?mul(481,330)+[ mul(542,441)%when()!^?select()when()select()$-mul(385,342)?who()how(),who()mul(394,223)@<$@-%%&:#mul(197,885){select()when()+)when():select()[mul(753,360)why()(>;!(mul(91,833*$#mul(979,895)where()@>mul(372,24)%*mul(189,679)mul(97,308)who()>mul(657,601)->*; #&)-mul(906,401) from()(what()mul(808,51)[<{when()mul(723,974)!'@)$^who():mul(947,448)mul(440,545)'<?mul(172,802)where()mul(716,119);when())do()])where()(#where()>who()]mul(319,32)<#select(232,786)select(91,643)what()where()mul(728,960){do())^ })mul(525,770))who(),;why() #&{why()mul(695,142)@]+ )[$&*mul(558,127)how()why(),<,&how()^>!mul(126,171):)}]&don't()^'how()+*^where()where()@mul(331,359) */do()what()):why();where()>mul(715,122)when()(when()from();,)}^$don't()/where()/^mul(242,204)how()mul(910when()what()[,]/&don't()-!how()who()who();from()}where()mul(353,405)where()from()what()who()mul(562,824)mul(333,11)mul(842,629)#}+$^mul(778,805)>mul(806,747)when()!^mul(741,908)why()where()mul(110,482)>&$?mul(579,772)@}select()-mul(636,907)(mul(526,945)-(from()(*what()how():mul(166,764)?'?#mul(246how()#{mul(476,49)*:who()who():,what()-+mul(477,38)&?{;>/mul(544,656),select()*what();what(394,396)[ ?&mul(514,32){^select()@select():#]%mul(964,815)mul(562,410);when();*mul(944,789)~/^$~$-mul(750,209)* ;;how()mul(487,591);?<mul(230,18)mul(380,386),-{,@select()^mul(949,615)!how(900,63)what()+mul(557,379)]@when()] :*(:~mul(423,189)where();:when()}{[ [*mul(844,661)mul(631,480)$mul(484,570)mul(761,125~#)*@~mul(286,807)mul(715,248)&<*,'{)mul(513,214)-what(531,549)*@$where()$#) mul(420,876)*what()!mul(177,619)select()< mul(819,380)?how(): <:';mul(263,636) | ||||||
|  | [}[%*:mul(763,577)}<<[],@mul(416,291)}<{how()[who()):@mul(80,21)mul(147,560)who()@',what()mul(9,445)]!mul(797,562)%[$-who()mul(128,286)from(){;:mul(331,938)*why()'-[what()mul(159,223)-*where()<who(619,345)-,mul(684,152)who()mul(433,596){mul(793,372)<from(54,483)[select()[where(629,864)mul(935,16)mul(204,768)!mul(864,108)from()don't() }$mul(147,548)^mul(827,996)mul(420,422)how()what()mul(61,127)@&<'^+^>mul(245,365)[[!@),{@mul(651,974)} /<mul(333,723)+mul(198,582)mul(631,8)what(),what()]!who()how()what()<mul(21,630)where()&]~:[mul(358,326)from()+from()mul(372,505)-:do()#?what()where()mul(351,931)>]%why()&mul(809,5~*/&&why()>mul(571,244)where()#why()}what()mul(518,122)+mul(579,300)'/select(898,768)>%][$(don't(){[mul(361,809)>[>&];why()why();mul(294,704)mul(331,74)}mul(694,47)]/-mul(399,272)when()mul(104,924)when()what(347,469)>from()~^mul(642,304)when()<what(){>?why()?mul(429,733)select()#&(}&mul(125,283)select()][who():[ mul(136,666)? when()where()%what()>/how()mul(570,389):]~who()+@!}mul(713,887)?{}select()'mul(98,67)&when()do()when()>mul(536,7)*when()) !'mul(884,110)@#')mul(201,681)from()^,do()'why()#]<why()'(;+mul(593,332)]mul(180,819)/@mul(902,212)-mul(90,446)~];select()why(100,859)!don't()-'mul(893,69),}][from()don't()+(~why())mul(86,991)mul(590,379)how()mul(405,424)?:#>from()! don't()when()how()mul(420,456)%?,'mul(385?select()mul(916,632)]mul)mul(908,719)$*@ <when() <$where()mul(539,350)(+why()# +select()select()mul(405,412)'!>({/{^<when(442,660)mul(143,163) who()why()mul(140,644)mul(250,287))mul#'-when()select()how()+/$mul(822,187)mul(888,819)!<select(908,31)[$/mul(212,723)who()&]mul(372,211)mul(854,457)&;where()??}-+/mul(198,967)from()mul(669,611):what(364,527)*);[select()^)/mul(62,603)-+@mul(215,373))mul(765,970)mul(218,4)^] mul(482,465)how()$^,];from()'mul(677,699)#mul(856,173)#mul(816,115)!mul(647,891)from();<[!select()-how()mul(726,735)who(),#who()how()mul(44,988@++!~mul(298,848): /]where()^where()why()who()mul(2,969)mulwhen(779,246)where(){when()how()>how()<mul(595,699)when(){why()from()mul(270,688)^select()*!~'<}-mul(324,127)(select()-mul(354,982)]+from()&#>?!mul(980,215)>what()where()@?why()-?mul(614,656)mul(220,163)?why()how()mul(355,585)%;mul(419,411)mul(184,742)$what()>;don't()],'$(select()mul(736}when(),mul(626,880)who()*<how();*]%(mul(676,2))+%who() how()-%+<mul(366?((how()>,;mul(765,856)<<>why()mul(553,221)^!>$who();mul(813,625)>]*  how()do()]<;$<@where()select(774,55);!mul(496,557)#<>,!>)what()mul(222,55)from()who()]',what()/;where()where()mul(136,746)>(don't()]mul(970,908)select()^@)'%mul(237,672):+<@<%%-}mul(498,420)who(839,971)&select()mul(937,73)$&&from()do()mul(996,665)&where()where()%,#mul(143,849)?from(913,546)*{?([&mul(134,708)why()[,'how(166,502)select()#&mul[-mul(205,222)}select()]}( why()@(+mul(898,124?*how()@select()mul(616,898)where(705,139)]@mul(155,570)who() -$,{&mul(89,802)!+who()$do()&~]%>?{ >mul(676,57)< <from()!((*&mul(91,478)]mul(105,40)when()]'how(669,25)mul(346,548)]]]'when()>mul(738,600):mul(918,629)['when()~where()from()!;:>mul(161,824)what())from()mul(600,436)~{]what()select()!+&%/mul(996,979)}}who()] $+$mul(206,328)$^)@@/,when()}%mul(130,592)when()select()%mul(50,834)';*@when()mul(73,823)mul(865,121) | ||||||
|  | ,^:mul(71,583)mul(316,791)from()when(){&->why()mul(495,908)@}*where(),how()%mul(645,82how(830,734)who()[mul(398,188)(%where()&do(){)from()from()who()mul(221,419)<:]$^'^)from()mul)mul(693,760)#how()>^why()why()[,'why(370,828)mul(516,571)where(425,351)<,>)mul(661,792{))$~-what())who()#[mul(325,165)[$where()%^*]who()+/mul(346,3)do()-@when() when()>+#*mul(698~ mul(248,163)/~]#{from()*mul(57,514)mul(871,508)[mul(498,284)from()who()select()when(277,99)*select()*mul(840,612)%mul(897,30)#</}^(do()<+select()@where()$when();#-mul(405,945)#why(433,827)>/mul(346,138)select()how()?)mul(354,691)?]what()don't();?;when(244,299)who();when()>mul(224,179)%]mul(50,319):mul(34,718)when()^:+where()from()'from()}mul(943,652)+/why()*why()#%don't() when()#'>+*>mul(231,697%how(175,144)mul(507,740)+~where() :from()mul(755,156)/%$)*+(who(212,81)>mul(927,385)#()do()mul(80,489):*,select()%&%where() mul(911,455who()}mul(651,799)~-why()+*mul(202,247);+%^:<mul(854,23){@#mul(961,171)where()!-mul(128,126)%%~#what()@mul(473,221)$do(){ !,&from(188,13)&!:where()mul(153,592)%select(112,432)where()mul(639,252)%]}$do()mul(504,573)how()mul(150,892)?who()+-why()%[}where()mul(602,833))-mul(53,697)%where(); /<where()$<mul(270,818)?how()}mul(185,555)/>mul(940,746),#from()when()mulwho()mul(701,602)mul(183,908)how()mul(12,827)][})how(){~when()$mul(332,704)^)when()when()mul(936,771)#where()/who()who();from()$# do()%where(){^ mul(953,541)mul(207,683),how()~%mul(336,694)why()>@<do()mul(783,475)~@mul(500,657)> *!?[from()@mul(924,686)*)%! / )why()[mul(493,198)when()>;<$how()$(]>do()(?~(!&^select()%mul(355,72)}how()~why()why()what()~'mul(936,935)&{what(803,472)from()]<who()@who()mul(17,105)where()^select()^&[<mul(869,268)what(){mul(135,402) {where()mul(732,550)where()don't()@~mul(240,194)why()~#how()mul(412,850)!$>@ ,do()@why()*why()[mul(149,595)}]mul(867,291)~&)'%<mul(330,855)(<how()%mul(712,568)(why()@when()where()~mul(913,542)$/ mul(370,272)]from()>@where()>from(455,831)%mul(646,518)% mul(522,755)];'who()from()select();what()'%mul(555,59)(how()'?[!@do():@{mul(729,27)when()]'*,/,why()where()mul(949,316)how()^who(84,611)[?:#mul(931,532)<% [where()select()@%%mul(383,846)$why()~{/+(@mul(325,437)who()>],select()#;when()%mul(601,128)<!mul(783,128)who()#select(532,884)how()]mul(928,854)<^where()/:what()(where(831,396)select()?mul(743,757)$}!{)%mul(723,274),!^{'(mul(125,779)+mul(104,510)mul(878,917)( where(389,343)%-)]mul(838,207)(^#$/</&mul(967,47)from()@{%?how()who()why()select():mul(590,941)~why()where()![-(mul(973,686)<!(,#{(/mul(787,692)~+mul(629,517)+why()-(>?mul(10,499)%mul(704,145) >mul(811,825);*{mul(539,875)mul(920,111)mul(509,272)mul(657,901)>mul(464,17)why()what()!why()*])}!mul(736,189)mul(299,45)when()select(169,279)><>[,mul(532,593){mul(627,971)how()who()how()where(291,392)/[): do()!mul(770,718)$&;!what()]?#^%mul(938,624)what():<#how()@!~mul(279,222)from()^++);:?why()$mul(98,818)$(]#{%-mul(891,49)+who(251,742)> what()where()<(mul(526,69)}%when()]/(~#do()select()**+^-from()mul(119,943)what()?from()when()*}<what()<]mul(577,966)select(){select()*['>( don't()mul(370,463)!why()>who()mul(326,383)!~how(59,628)!; %do()mul(671,969)!mul(747,375)mul(257,559)!?#!/<how(315,722)(mul(529,781)<'[%?$mul(118,474)mul(866,674)%mul(99,500)?[who()do()who(394,637)^(+ [#(?{mul(555,282){-[*@!'select()where()don't()*{what();why()&>*mul(353,892)select()why()(mul(648,3)how()don't()<~{mul(771,164)mul(576,453)$why()}-@'mul(967,581)* %{:when()where(){*< | ||||||
							
								
								
									
										140
									
								
								y2024/resources/4_input.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								y2024/resources/4_input.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | MMSMXMSASXMXAXMAXSASXXXMASAMXSMMMXMMXMXMASMXMASMSMXSSXMASXSMMSASMSAXAMXMAMMMSAMXXXMAMSMXMMMXMASXMAXXMMMXMMSAMXAMMSMSSMSMMMSMMXSXXAXMXSAXMASX | ||||||
|  | XAXMASMXMASASXSXAMAMXMXMAXAMXSASAMXMAMAMSAMSSXMMAXASXAMAMSMAXMXMASMSASASASAAMAMXSMSMSAXAAXXAMSSMXMXSMAMXXAXAXXASXAMAAXAAXXMAXAXXMMSSMSSXSASA | ||||||
|  | XMASXXXASAMAMASMMMAMMSASXSXMASAMMAXSAXXXMASXMASMSMMMMXMAXAXXMSAMXMAAXSASASMXSAMAAAAXSASMMMMMSAXMASAMSAMSMMSAMSAMAMMXSMSXMASXMASAASAAXMAMMAMM | ||||||
|  | SSMSMSSXMMMAMSMAXMAXXMAMMAMSXMSMMMXMAMSXSSMXSAMXXAASXMSMSMSMMSXSAMMMMMAMXMXAMASXMSMMMXMAAAXMMMSMAMAMMMMAAXMAMSAMXXXMAMAASXMAAXXMXMSMMMSMMAMX | ||||||
|  | XXAXAAAMMSSMMXASXSMSSMAMSAMXAXXXASMMSMSASAMXMASMSXMXAAXXAAAAASASAMAXSMSMSSMSSMAAXAXAMXMMMSXXAXAMSSSMMSSMSMSAMSMMSMXMMXSMSASXSXMMSMAMAAMAMASX | ||||||
|  | MMMMSMMAAAAMASXMAAXAAMSMXAMSAMXSMXAAAAMMMAMASMMMASXSMMSSSSSSMMMMMSAMSXASAAAAAMMXSXSMXSSXSAXAMMMSMAXAAXAMXAASAMXMXAMXMAMXSAMMMXXAAMXMMXSAMAAX | ||||||
|  | XAAAXAXMMSSMASAMXMMSSMMASMMSASXMXAXMMMMAMMSAMAAMAMXAXMMAXAMAMXSAMMMMMMMMSSMSMMXMAMMMAMXMMAAXMASAMXMMMSAMSSMXMASMASMAMXSAMXMAAMMMMSSXSASASXMS | ||||||
|  | SSSSSSMMAMXMASXMAMXXXAMAMMASXMASMSMSAMXSSXMASXMMSSSMMAMMMSMMSSMASAAXAAAAXXAMXSASMXMMXSAXMSMMSMSASXSSMMAMAXXXXAXSAMXXSAMASASMSSSXSAMAMXSXMAXS | ||||||
|  | MAMMMAAMSSSMASXSSSSMMMMAMMAMASAMAAASXMAMMMMMXMASXAAXMXMXAMAXSAMAMXSSSSMSAMXMASASXMMAMSAMXXXAAAMAMXMAMSSSMMMXMSXMMSXXMASAMMXAXAAXMAMASAMASMMS | ||||||
|  | MAMMSSMMAAXMXSAMMAAXAAXMMMXSASAMMMXMSMMSAAXXAMXSMXMMMASMSSSMSAMXSXXMAXAXXMAMXMAMXAMAXMASXMMSMSMSMMSMMAAMXMMAXMASAMXXMAXAMXMXMMMMSXSAMASAMXAX | ||||||
|  | SMSXAMMSMSMSAMAMMSMMSMMAAAXXASXMAXSAMXAMXMSXSAMMMSAXSASAAAAASMMASMMMMMXMXSSMSAXXMSSMXMAMAMXAAAAASAMXMMSMSXMASMMMXASMMMSAMSSMSSSXSAMXSAMASMSS | ||||||
|  | SXMMXXAXXMAXXMAMXAXAAMSSMSXMMMAXMSMSMMMMSXXMAAMAAMMXMASMMSMMXASAMAASAMXSAAMAMAMSAMXMAMSSSMMSSMXMAMMXAXMASXSAXAAMSAMXAAMAMXAAAAAMMAMAMMSMMAMS | ||||||
|  | SAXMXMMSMMSMMSMSSMXMSAMXAMXSMMSMMAMAMMMASAMMSMMMXXSASXXXMXXMXMMASMMXAMAMMSMMMAMAAMAMASAAAAAMXMXSMMSSMMMSMMMMSSMXXAXMMXXAMSMMMSMASXMMSMAXMMMM | ||||||
|  | SXMMAMMAXMAXAAXMASAMXAMSASAXAAMMSMSASAMXSAMXXXXMAASXXMXMXAXXAXSXMAXMSMSMMXMXSASXMSSSMSMSMMMSAMXSAMAAAXMAXXAAMXMASMXMASXMMXAMXXXXASXMAMXMXXXX | ||||||
|  | XMASXSSMSSXSSMXSAMMSXSXSAMAMMMSAAASASXSMSAMXSMAMMXMMSXSAMSMSSXSXSXMAXMXAAXSAXAMAXAXAXXXMASAMAMASAMXSMMSMSSMSSMSAMMASAMASXXXAMXXMAAXSAMXMSMMM | ||||||
|  | MSXSAAXAAAXXXXAMXMXMAMAMXMXXAAMMMMMAMAXAMAMAXMMXSAXSAAXSAXMAMMXAMSSXMASMMMMASAMSMMSSMMMSXMASAMXXAMXMXMSAMXAAXXMAXSAMAMAMXSSSMSXMXMMMXSAAAAAS | ||||||
|  | ASAMMMMMMSMMAMXXMMAMAMAMXSMSMXXAXAMMMSMASMMSXSMASXXMMSMMMMSSSSMMMAMMMAMAMSSMAXXXAAAAAMAMASMMMMSSMMXMASXMSMMMSMSMMMMSAMSSMMAMAAMMMXMAAMMSMSMS | ||||||
|  | MMAMXXAAXAAMMMSAMSASASAXAXAAMXSSSMSXAXMAMMAXAAMMMMXAAMXXMASAAASXAASAMXXAMAAMASMMMMSXXMASMMXASAMAAAAMSMAXXAAAAMAMMMMMXSXAMMAMSMSAAXMMMSAMAMXX | ||||||
|  | MSSMXSSMSSMMAAXAXSXSMSXSMMSMMAMXAXMMMXMAXMAMSMXSAMSMMSASMSSMSMMMSSMXMMMSMSSMAXMAAMXMSMMSMASAMASXMXMSASXMSSMSMSASAAMMMMMMMMXMAASMSMXXAMXSAXMX | ||||||
|  | XAAXAMAXAAMSMSSMMMMSAMMAMMMMMAMSAMXAXXSMSMSMXXAMMXAAAXAMMMMMMAMAXAAASASAAMXMASASXSAXMASMMAMXSMMXSAMAXMMMMXMAASASXMMAASASXSMSMXMAMXSMSSMMMMSM | ||||||
|  | MMMMMSAMSSMXMAAASAAMAMSAMAAMSSMMASXXMAAAAXXAMMMXSMSXMMXMXAAAMAMXMSMMSSSMSMMMASMXAMMMXMMAMXXXXASASASAMXXSAMXMMMAMAMSSMSASAAAAMAMAMXSAMXAXAXXA | ||||||
|  | SXSAMXMMXXAAMXXMMMMXXMMASMMMAAAXAMAASMMMMMXAXAMAMXXASXXXMXSSMMXSAMXXXXMXMXAMXSXMMSMSAMMXMASMSAMMSMMMMMMMASMXSMSMSMAMAMXMMMSMMAXAXXMMMSSMSXSM | ||||||
|  | AAMSMASXAMSSSSXSXXSSSSSXMAMMSMMMMMSMMAAXXASXMMMASXSAMAMSMXMXAAAMSMSSSMMASXSMASAMXAASASXMXAAMMXMASAAAAAXMSMMAAAAAAMSMXMSXMMMMSMSMMMXMASXAMASM | ||||||
|  | MMMXMXSMXMAAAMASXMXAAAMSMXMXMXSAXMAXXXMMMMXMAMSAMXMAMAMAASASMMMMXMAXMASASMAMAMAMMMXMXSASMXMXMSMASXSMSXSXXAMXMMMMMSXMASMMMAAXXMAMAMAMXSMSMAMX | ||||||
|  | SXMASMXAAMSSSMAMAAMMMMSAMAMMSASXSMSSSMAAXSAMAMMASXSSSMAMMMAMXSAMAMASXXMAXMAMMSSMSXXMAXXXAASAMXMAMXMAMAMXSAMMSXASMXMMSAMXSMSMMSSSMSASAXAAMAMA | ||||||
|  | AAXASASXMMAAAMSSXXSXSXSAMMMAMXSXXMAAAAXSXXAMXMXAMXXMAMXXXSAMXSASMXSMAXMSSSMMMAMXSXAMSXMMSMSASMSSMMMXMAMASAMAXMMMSASXMASAMXAAXXXAASAMMSXSXSSS | ||||||
|  | SSMAMASAMXMSMMXMXMXAAASMMSMSSXMASMMSMSSMMSMMASMXSSSSMMSXMSAXASAMXXMASXXAXAAXMAMMMSMAMXSAMXSAMXAAAAXMSXMAMAMSXSXAMMMXMAXAMSSMMAMMMMXAXMAMAMAA | ||||||
|  | AMMSMAMXMMMAMXAMAAXAMXMAAXAAAASMASAMAXAXAAAXAXMMMXAMAAAXMXXMXSXSMXMAMXMMSMMMSAXAAXMAXMMASAMAMMXXMMXASMMMSMMMASMMSASAMXSXMAAAMXMAXXMXXMAMAMSM | ||||||
|  | MXAMMSMMAXSAMSASMSAAXXSMMXMMSMMXMMMSXMAMSMSMMMXAMXMMMMSSMAMSAMXXASMAMXAXXAMAXMSXMXMMSAMXMXMAXMMSMSXSXASAAMAMMMAXSASASAMAMSSMMASMSSMMSMXMAMXX | ||||||
|  | XMASXMAXAAMAMSAXAMMMMMSASAMXXMXAXAAMAMAMXAXMSMSSSMSAASAAMAMAAXAXAXAASXMMSAMSSMSAMSAMMMMAMMSXMSMAASXMSMMSSMXSMMSMMXMXMASAMMAASXSAAXXAAAXMSMSM | ||||||
|  | AAMMMXAMXSMSMMAMMMAMAASAMXMSMSSXSMSSXSASXMMAMAAAAAXMSMMSSSSMSAMSXXXMSAMXMAXXAASAASMSASMAAXXXSASMSMMMAXMMMAMXMAAAMSMMSXSMSSSMMAMMMSMSSSMAAAAA | ||||||
|  | SMSASMMMMMMXAXXMAMAXSAMXMAXXAMXXSMMAASASMXMXMMMSMXMXXAAAXAAAMXMAMSSMXASXSMMSMMMAXMASASMSMMXXSMXXAMXSAXSAMXMAMSXSAAAXXAXAAAASMMMAXAAAAAMSMMMS | ||||||
|  | MAMAXXAAAAMSAMXMSXXXXAMXSXMMAMSMSASMMMMMAMMMMAXAXMSMXMMSMMMMMMMASAAMXMXMASAXAAXXMMAMXSXMAMSAMXSAMXMMMXMSSMSXXAMXMSSMMMMMMSMMMMSXSXSMSMMMSMAX | ||||||
|  | MXMMMSSSSSXXAMXMAASASAMXMAXSAMAAXAMXXAMAMXAAXMSMXMAAASAMXSXAXAXSMMSMASMSMMSXSMSXMSXMMSASAMMMMAXMMXMAMAMXMMXXXXXMAXAAASXMXAMXAASAMXMAMXAAAMXS | ||||||
|  | SSSSMAXMAXXSMMXMSSMAMMSAXAMSASMSMAMMSMMSMSSSXMSXSSMSMXAMXSSMXXXAAXMXAXAXMAMMMSMAMSAMAMAMMMAXMMSMMMSASMSAMMSMSMMXSXSSMSASMMSSMMSAMXXAMSMSXSAS | ||||||
|  | AAAXMMSMAMXMMAMXMAMXMASMMMXSAMAXMSXXAAAXAXAMXAMAMXMXMMAMAXAMASXMMMMMSSSXMASMMAXAMXAMSSXSXSXSAAXAAXXXAXSASAAMAAMAMXXAASAMAAAAXASAMXSSXXXMAMAS | ||||||
|  | MMMMAAAMMXXAASMSSMMXMAXXAXMMXMXMMAAMMMMSMMAMMMMSSMXAASXMMXXMAMAXAAAMAAASMAXAMSXXXMAMAMMSAAMSMMSMMSMMMXSAMXMMMMMAXXXMMMSMMMMSMXMMMXXMAMMMXMAM | ||||||
|  | MAAXMSMSAMXSXMAAAASXMSSSSSSMSMMAMMMMAAMXXMAMAXAAAAMSMSAAMMSMMSSXSSSSMAMMMAMSMXAASXSMSXAMMMXXAXXMXXAAXAMXMXSSSSSSSMSAXMASXSXMMSMXSSMSAASMSMAM | ||||||
|  | SSXSAXAMXSMMAMSMMXSASAAXMAMAAAMXMAASXSSMMSMXSMMSSMAXAMXMMAAAMAXAAXMAXMXXXSXMAMAMXAMAMAXXXXMSSMSAXSSSMMSASXAXAAAASAAXMASAMXAMAAXMXAAMSXMAMXAM | ||||||
|  | MAAMXMAMAMAMSMAXXAMMMMMMMSMXSSMAMSXSAAXAMAMAMXMXMAXMXMAMMSSSMASMMMSXMMSMMMAMXMMXMMMAMMMSMMAMAAAMMMAXAASAXMMMMMMMMSMMMMMAMMMMXMMAMMMMMMMAMXSS | ||||||
|  | MMMMXMAMASMMMSXSMMXAXXXAAXMAXAMMXMAMMMSSMXMAXAXMASMSMMAMAXMAMXSAAXXASAAAAMAMAMMMAASXMXAXAMSMMSMXMMSMSMMMSMXAXMASAXXSAAXAMAASASXSMSAMXASAMMAA | ||||||
|  | XXAXASXSXSAAMAMMAMSMSMSMSMMMSAMXAMXXXMAMAXMMSAMMSAXAASMSXSSXMASMMMSAMXSSMSAXAXAMXMMASMSSSMAAXAMAXMMAMXXAAMASAMXMASASXXMXMXXSAMAXASMSXMSASMSM | ||||||
|  | ASMSASASASMMSMMSAMAMAMAMMASMMMMXSMMSMMASMMMAAAMXXAMMMMAAAXMSMASAMAXASAMXXSAMXSMSAMSAMMAAASMSSMSSSXMAMMSSMSAXMAXSAMXMASMMSSMMXMXMXSAMXXXAAAAX | ||||||
|  | AAAMAMAMAMXMAXAXAMXSASMXSAMAAAXSMAMMASAMAASAMXMXSXMAAMMMMMAXMASAMXXAMMSSMMXMXAAXAMMXXMASXMMAAXAXMAMASAMXXMXMAAXASMXMAXAAAAXAMXXMMMAMASAMMSMX | ||||||
|  | SSXSAMAMAAAAXMMMSMASASAAMXSMMMMMXAMSMMXSAMXMSMMAMASXSXSAXMMMMMXXMMMSXAXAAAAXMMMMSXMMSSXMAMMMMMMXSAMXMASMXSMSMSXSXSXMMSMSMMMMSMAXAXAMSMAXAXXS | ||||||
|  | XMAXMSSSMSSMSASAAMXMMMMMSMXXAXAMSMXXXXXAMMAAAAMMSAMXMAMAMMAAMMMSSMAMMMSSMMXSASXAMAAAAMASXXSMSSXASAMMSAMXAAXAAXXXAMXMAAXAXAAXAMMMMSASAXMMMXXA | ||||||
|  | SMSMXAMAAXAAXAMMSMAAXASXSAMSMSMMAMXMMMMXMSXSSMMXMAMAMAMAAXSMXAMSAMASAXMAXAXSAMMMXSMMXSAAAASAMXMASAMMAMXMAMSMSMAMSMAMSSSSSSSSMSAAMMMSASXASXSM | ||||||
|  | XAXAMXSMMMMSMXMAXAXMSMSMSAMXMAXXMMAXAAMXXMAXAASXSMSXSASMSMXMSAXMAMXSAMXMMMXMAMXSAMXSMMMSMMMMMAMMMMMSAMMXSAMXMMMMAXXMXXXAAMAMXSXMXAMXMAMASAAX | ||||||
|  | MSMAMAAAAAXMAMXMXAXMAMXAMMMXMXSMASAMSSMXMMXMSMMAAAAXMASAAXAXSMMSMMMSAMMSAMXSXMAMAXAAAAXAMMXSSMMSAMXSAMAAMAAAXAXSSSMSMMMMMMAMMMMMSXSAXMAXMXMM | ||||||
|  | MAMAMMSSSSSXSSXMMSXSSSMSMMSXSAAMAMMXMAXMXXSAMXMMMMMXMXMXMMMMXSAAAAAXAMXMASAMXMXSAMXSSMSMSMAAAXMXSAAMAMMSSXMXSAMMAAAAAXMASXXSAAAMXMSASXSMSASX | ||||||
|  | SMSXSMMMMAMMMMAMAMMMASAMXXAAXSSMSASMSAMMMMMMMMSAXSMXXASASMXAXMSMSMSMMSSSMMXXAXAMASXAAAAXXMMXAMMMXMMSAXAMAMXXXXSSMMSSMMAMAXASXMXSXAXAXAMASASA | ||||||
|  | SAAXXXAAMAMAAMXMXSAMMMMMAMMSMXXAMAAAMXMAAXAXMASAXSAXSAXASAMXSXXMAAAAXAMAMAMXMXMSAMMSMMMMSXSSSXXAXAAMMMMMSAAXAMAAXXXAMSAMXMAMXMASMSMMMAMMMMMM | ||||||
|  | MSMXMSSXSASMSMSAAMMSXSASMAAAMXMXMXMXMASXSSMSMAMSAMAMMSMMMMMXMASXMMMSMASMMASASAMXAXAMXMAXAAAAAASMMMMSMAMAMSMMMMSAMXXMMXXSASASAMMSAAASXSMSAMSM | ||||||
|  | MAXAMXXMSXSAAAXMMMAMASAAXMXSMAMSMMXSXMAMMAMXMXSAXMMMAAXMAMMAMXMXMXAMMAMXSXSAMAXSXMXMASMSMXMMMMMAAMMAXAXAMASAXXMAMMSSXSASASAMXSAMXMSMAAASAMAM | ||||||
|  | SASXSASMXAMXMMSASAMXAMMMSMAMXAXAAAAAAMMSSMMASXAMXXSMMMMSSMSASAMXSMMXMXMAMXSMSSMSXMAMXMAAXAMASXSSMMSSSSSXSAMSAMXSMAAAAMAMMMMMXXXSXXMMSMMMMSXM | ||||||
|  | MAMXMMSAMXXXXXAAMXXMAMAAMXAMSMSSSMSSXMXMAXSASMAXSAXASXAAAMSASMMXSAMSXMMSSMMAAXMXASAXSMSMSXSASXMAMAXMAAXMMMMMXMAMMMMSMMMMXAASMSMMMMMAAAXSASXS | ||||||
|  | MAMXMASAMXMXAAMMMXMAMSMSSMMMAAAXAXAMXMXMXMMASASXMASAMMMMSAMMMXAAMAMAAXAAAMMMMSMSMMMSMAMAMXMMSAMXMAMMSMSMMAAXMXSMSAMXMASMMMXAAXMAAAMSSSMMXSAA | ||||||
|  | SMMMXASXMXSXMXMAXAAAAAAXAAXSMMMSMMSSSMXSAXMAMXXXSAMAMSMAXMXSAXMXSAMSSMASXMXSAXAAMAMAMAMAMAMASMMSMSXAAMAAMXXMSAMXSAMXSASAMSSMSMSMSSXMMXASXMMM | ||||||
|  | XMASMMSAMXXMMAAXMASXSMSMMSXMAMMAMXMAXMAMMMMMSXSAMXSAMMMMXXAMMMMASAXAMMXMAMMSAMSXSASASMSMXAMAMXXAAMMMMSSSMSSXMASASAMAMXMAMXAAXAXMAXAAASMMXAMS | ||||||
|  | MSASAXMAMXMAMASMSMAAAAAXAMASMMSASMMMMMAXAAMXMAMXMASASMASAMXSSXMASXMASXXSXMXMAMAAXAXAMAAXXXMMSXMMMMAXXXMAAAAXSAMAMAMSSMSAMXMMMMXMAXXMMSXSMMMM | ||||||
|  | AMASXMSSMAMSXXXAAXMMMXMMXSAMAAMAMXMXAMMMSMSAMAXAMXSAMXAMAASAMXSASAASAMXSMMASAMMSMMMSMMMSXXAXAXSAMXSMMXXXMMSMSMMSMSSMAASMMMSAAMSSMSSSMSMMASMM | ||||||
|  | MMMMAMAMXMAMAMMSMMXSMMXXMMMSMMMSMMMSSMSAMASXMMXMSAMAMMMXMMMXSAMAXXMMSMAMAXXMAXAAMAAAAAXAASXMSXSASAXASXMMMXXAXSAAMXAMMMMAAASMSMAASXAAXMAMAMAX | ||||||
|  | XSASAMASAXMMAMAAASAMAXMSSXMAMAMAAAXMAAMAMMMSAAASMMSAMXMASAMSMMSAMSSMAMASXSXSXMSSSXSSXMMXXSAAMASMMASAMMMASAMXAMSSMSAMSSSMMMXAAMXXMMSMMSSMSSSM | ||||||
|  | ASASMXASAXMAAXSMMMMSSMAAAASMSMSSSMSMXMMSMSASMSMSAXMASAMASASXAAMAXMASAMXSAAAAAXMAXAAMMSXMMMMAMAMAMAMAMMSASXSMAXAMMSAMMASXMAMSMSSMMAAAAAAAAAXA | ||||||
|  | XMMMXMASASASMXMMSAMAMMMMSXMMMMAXAMMMMMXXAMAXMMASMMXXMXMASXMMMMSXMSMMSMAMMMMSSMMAMSMMASMMASXSMSSXMXXXMXMASAXMMMMMASAMMAMXMAXAAAASASMSMSMMMSMS | ||||||
|  | XMXAAMXMAXMAXXAASXMASXMXXMXAAMSSXMAAAMXMXMMMSMAMAMXSMXMASAMXXAAAXXXAAMXSXXXXXMAMAXAMXSASXMAMXMAMXXMASMMXMAMAAAXMAMAMMSSMSMSMSMAMMXAAAXMAXAAX | ||||||
|  | MSMMMMMMXMXMSMMMSMMXSXMAMAXSSMXXXSXXXSMSASAAXMMMXMAMAAMMSXMMMMMMMAMSMSXMMSMSMMSSSSXMASMMMMSMMMAMAXSAMAMMMMSSSSSMASAMAMSAAAXMAXXAXMMMMSSMSMSM | ||||||
|  | AAAMASMMAMXXXAAAMAMXMMMMSSMMMMSXMAXSAAASAMMSSXMMXMASMSSMSMMXXMASXMMMXMAAAXMMAMAAMMAMAMAMAXMAMMAMMMMAMAMAAMAMXAAMXAMMAMMXMXMSMSSMXSXAMXMXAAAM | ||||||
|  | MAXSASAXAXMXSSMSSSXAXAAXAMSXMASAXAAMXMMMSMSAMAASXSASXMAXMAMMMMAMAAAXASXMSSMSSMMSMSAMAMAMSMSAMMMASXMASMSSXSAXMXMMXMASMSMSSXMAMXAXAXMXSAMMMMMS | ||||||
|  | ASAMMSXSMMSAAMXMAXMASXMSAMXSMAMAMMSMMSAMXMXAMMMMAMASMSMMXSMAAMASXMMSXMMSMMAAMMMMMXMSMSSMMASXMASASASAXMAMAXXMASMXMXAMAAAAXXSASMMMSSMMMASAAAXX | ||||||
|  | AMAMXXXMAAXMXMAMXMXMAMXSAMXSMMXAXXAAAAXXAAMXMASMSMXMMAXAAXSSSMASAAAXXSXSAMMMSMSMAAMXMAMAMAMAXAAASAMXSMSMSMAXMASASMMMSMMMSMMXSAXAAAXAMAMMSXSM | ||||||
|  | XSSMMAXMMMSMMSAMSAMXXMASAMXMAMASMSMSMMMSASAMXMXAXMSMSASMXMAXXMAMXMMSASASXMASXAAMSMSXMASXMMSSMSMXMXMXMMAAMSAMXXSMMAMXAAAXSAMASMMMSSSSSMSAMAAM | ||||||
|  | MAXAXXMASXXXASXSAMASXMXXAMXMAMMXAXMAAAASXXAAMXMAMAAMXAXAAMSMMSMSMSAXAMMMASMMMSMMMAXAMAAAMAAAAMXSAMSMSAMMMMXMAMMXMAXSMSSXSAMXMXXMAMXXAAMAMSMM | ||||||
|  | XMSMMMSAMXAMMSMAASXSMSMSSSXSASXMASXSSMXMASMMSAMAMSMSXMMSXSAAMAAAAAXMXMASASAAAXMASMMXMMSMMSXMMMAMXMAASMSAAXSSMXSASXXXXAXMXAMAMSSMSSSSMMMAMAXX | ||||||
|  | MXAXXXAMMMXMASMXMMAXAAAXAAAXASXMASAMXMAMAMXAMXMXXXMAMMAXMXMSSMSMMMMMSSMMASAMASMMMMXXXXAAXXAMMMMSMSMMMAMXSXMAAXSASMMSMSASXSMSMAAMAAMMAAMSSMMS | ||||||
|  | SSMXMSASASASMSAXSMSMSMSMMMMMMMMMXSXMASXMSSMSMSASMMMSMSASAMXXXAMXMAXXAAXMMMAMAXMAAMAMXSMSASAMXASAMASXMXMAMASMMMMAMXAAMAAMAXAXMAXMMSMSSMSMAMAA | ||||||
|  | XASAASAMMSASXXMMSAXMAXXXSAXAXAXMXMASXMXAXMAMAMASAASMAAXMXAMAMXMXSXXMSSMMASAMXSSSXSAMXXXMMMMMSXSAXAMXAMMMSXMAMXMMMMMSSMSMMMMMAXMXXAXMAMAMAMSM | ||||||
|  | SAAMMMAXMMAMMSXMMAMSMSMAMMSMXMSMXSAMMXMAXMXMXMAMMMMMMMMXXXAAMASXMXXMAMASXSASXAAAASMSAMXMXMSAMASAMSSSMXAASASAMMXXAASAMXAAAAAMXMMSAMSMSSSMMXXX | ||||||
|  | MMMMXSXMSMSMASMSMSMXXAMAMAXXASAXXMAMAXAMMSMMXMXSXSASXMAXSXSMSXXAMXXMASMMASXMMMAMXMASXSAMAMMASAMXMXAAAMMMSASMSXMSSSSXMMMSSSXSAMXAAMMAAAAASMMM | ||||||
|  | XMXSXXXXAAAMMSAXAMSSMSSMSXMAMSASXSSMSMSXAAASAMXMAAASMXSASAXXSASMMMMSXMXXMMAMXXMASMXMASMSAXSAMMSMMMSMXXXAMMMXAAXAMXMAMSAAAMASXSSSSMXSMSMMXAMX | ||||||
|  | MMAMMXMMMSMSXMMMSMMSMASAXMAXXMAMXAXAAAMMXSSMXSMSXMXMASMAMAMAMAMAAAAMAMXMXSAMMMSAMXMMAMMSAMMAMXAAXAMXSAMXSASMSMSAMXSAMMMMSMXMAXAXXMXMAXXMXSSS | ||||||
|  | AMASMAMSAXXXMASAXAAMMAMXMMSMMMXMAMMSMSMSMMMMAMAXMASMXXMSMMMAMMMSSMMMAMXAXSMXAAMAMSAMMSAMXXSMMSXSMXMAAXASMMAXMASAMXMSSSXMXXAMMMMMAXSMMMSAMXAM | ||||||
|  | XSAMXAASASMXMXMASMMSMXSAAMAMAAAXXMAXAMAXAMAAAMSMXAXAXAAXMASMMSAXXAASXMSSXSMSSMXAMSXXMXAXMASAAMAMXSMASXSAMXMSMXMAMSAXXAASMSXSAAAAMMMAAXMASMSM | ||||||
|  | MMMXXMXXAMXAMXMAMAMXAXSXXXAXMSMSAASMSMMMMSASMSXMMXMXMASMSMSAAMAMMMMSAAMMMSAAAMSMMMMMMSMMSASMMMAMASAMXMMMMAMXMASXMMMMMXMMAMXSMSSXSASMMSMMSAAX | ||||||
|  | SASAXSSXSMSSSXMSSSMMSMMASXMSAAAMXMXAAAXAXAAMMMAXSASXAXMAAXMMMMSSXMASMMMAAMMMXMAMMAAMMASXSAMXXMASXMXMAAAXSXSAMAMMMMSSSMXMAMXSAMAAMXMXMXMAMMMS | ||||||
|  | SAMMSXAAMAMXMASAAAMAMAXXMAAMMMMAMXMSSSMSSMSSXSMMMAAASMXSMMAMXAAMAMAMAXSMSSXAASASMMSMSASXMAMXSAMXAAXSXSXMAXSXSXSAMXAAXAASASXMAMMMMSMXAAMXSAMM | ||||||
|  | MAMXMMMMMSMASXMMSMMASXSMMXMXMXMASXMAAMMXSAAMAAXXMXMAXMMXMASMMMMSAMSSMMMAMMMSXSASAAMAMAMASXMXAAMXMMMSAMXMMXMASMSXMMMSMXMSAXMMXMAXAAASXSSMXASX | ||||||
|  | SASAMSAMXXSAMXSAMXSMMAAXAMXASXMXAMXMMAMAXMAMSMMXMASXSMMASXMASAAXAXMAAAMMMMAMASXSMMMAMAMXMAMMSMMSXMASAMXMSAMXMAMMSSMMAXMMMSASXSSMXXMAMXAXXAMX | ||||||
|  | SASAXMAMSXMXXMXASASMMMMMMASXSASMSMXMMXMASXXMAXSASMMXMASAMASAMMSMMMSAMSMSMMXSAMXXMAMMSXMAMAMAAAMAAMASAMMXAXSAMSMAAAXMSMXAAMAMAAXAASXMXSAMSSMX | ||||||
|  | MXMMMXSMSAAMSMSXMASXXAAMXXXAXAMAAXMASMMMSAASAMSMSASMSAMASXMASAXAXAXAMXMAAXAMAMMMXMSMAAXSXSSSMSAMAMAXAMAAMMSASMMMMXMMAAMXMMMMMMMSXMAXXMAMAMAM | ||||||
|  | SMMMAAMASMMMAASAMXMAXSSSXMMMMSMSMMSMMMAAMXMMMXSXSAMXMASXSASXMASXMXSSMXXSSMMSMMMSAMAMMSMXAAAAAAMXMMSSXMXAXAMXMAAAMSXSASMSXMAMAMXMASAMASMMASMA | ||||||
|  | SASMMSMAMMXMXSMMSAMXMXAXXMAXAXAXAAAAASMMSAMAMAMAMXMASMMASAMXMAMASMXMASXMAXXAAAASASMSAMAMSMMMMMMASAMXMSXMMSSMSSMXXAASAXAXXXASASMSAMXMXMXMASXS | ||||||
|  | MAMXAAMXMMAASMMXMAXMSMAMMSAMSSMMMMXSMSAASASASAMSMMSMSAMXMAMXMAXAMAXSASASXMSSMMXSXMXSXMAMAAAXXXSAMAMXXMAXSAAAXXSXMMXMAMSMMMMXXXAMMSMMAXAMXXMA | ||||||
|  | MXMAXXXAAMMXAAXSMSMAAMAMAAAMXAMSMSMAAMMMSMMMMMSMAXXXSXMAMAMXMAMSSSXMXSAMXAMMASMMXMAXXMXMSSMSMMMMSMMAMSXMMMSMMAASMSSMMXMASXSSSMXMAAMSSSXSXMAS | ||||||
|  | MSSSMASXSMSXSAMXAAAMXMAXSMXXMAMMAASMMMAAXMXMAMAMMMMXMASMSXSAMAMXAAXMAMMMMXMSAMAMXMASMSAMXMAAMSAAAAMXMASMAMAAMXMAMAAASMMSMMAAMXXMMXMAAMASXAXX | ||||||
|  | AAAAAMAXMAAMXASMSMSAASMMXXMMMAMMXMXXAMMSAMXSXSSXMAXMSAXMAAMMMAXMMMMMAMMAXSAMXXASAMXSAAASAMMMSSMSSSMASXXMASXSMMXSXSMMMAMXAMMMMMASAMMMSMAMMSMM | ||||||
|  | MMSMMXMXMMMXASMAMAXAMAMXMAAXMMMAXSMSXSAMXMAMAXMASXSAMXMMMXMXSSXSAMMSSSSMXSMSMSASAXXMAMXMASAMXXXMAMXAMSXSMSAMXMAMAMASMMMSAMXAAXMMAXAXXMASAAAX | ||||||
|  | XMXAMXXMMASXMAMXMAMAXMSXSSSMASMMSAAAAMXMAMASMSMAMSAMXMXSAXSAXMASASAAMAAMXXAAAMMXAMSASXASAMAMXMMMMMMAXXMAAMXMAMAXASAXAAAMASMSXSMSAMMXMSAMXSMM | ||||||
|  | SXSXMXMASASAMXSMMASXMMSAAAAXAMAMXMMMSMSSMSAMMAMMSXMXAMASASMAMMXMAMMSMSASMSMMSMSMAMSAMMAMASXMMAAAAMXMSMAMXMASXSMSASMXMMASAMXAASAMXXSAXMASAMMM | ||||||
|  | XXXXXMAMMASMMAAASXSAAAMMMMMMMSAMAXMXMXMAMMAXXAMXSMMSMSAMMMMASMMMAMXXAMAAAAXAXAXSMMMAMAXSXMAXMXSSSMSAAMXSAMXAAAAMMMXMMSXMXMMMMMAMAAMAMXMMMSAX | ||||||
|  | SAMMMSXMMAMMSSSXMMSXMMSXMASXXSAXSXSAMASXMSAMSMSMSAXAXMMSXMMAAAAMMSSXAMSMSMSMMAMASXSAMSMMASMMSAAAAAMSMMMSMSMMMMSMAAAXXMAMAMSXSXXMMXSASAMMXSMM | ||||||
|  | MAMXAAAMSMMMAXMAXAMAXAXMMASMASAMXAMMSMMMXMMXAMAXXSMMMSXSAXMSSSMSAXXMAMXAAAAMXXAMMMMAXMAXAMXAMMSMMMMASAAXMAMXSAMXMMMXAMAMAXSASMXXAAMAXASXMXAA | ||||||
|  | SAMMMSAMAAMMMSSSMMMAMSSSMAXMAMMMMAMXSMAMAMXSASMSMMXSAXAMXMXAMMAMXSMXMMMSMSMSASMXXAXSMSSMSSMXSXMASXSASMSMMSSXMASXSAAASXMSMSMAMAMMMMSSSMMASXMM | ||||||
|  | SASAAXXSSSMAXMAMASMAMAAMMSSMASMSSMMMMMAMAXAXXMAMAAAMMMSMMMMMSMAMSXMASXAMAMXMXMSASXSMAXMMAAMXAMSMMMMMSAMAXXXMXAMAMMSMXAMXXAMMMMXAMXAXAXSXMASM | ||||||
|  | SMSMMSAMAXMMMMAMAMXSMMMMAXAMASAAMXAAMSMSXSASXSSSMMSXSAAXAMAMAXAXMASASMMMMMAMMMMXMMAMSMXMMSMSMMAMAMSAMXSMXMAMAAMXXAAXXAMSSSMXAXXXSMXSMMMASAMX | ||||||
|  | MXXAXXXMMMSMMSXMASAMAXXMMSAMXMMSMSSMXAAAAMXMAAXAXAXXMMMXMSASMSMXSAMXXXXAXSASAAXMASAMXMMXXAXXXMASASMXSAMMASAMSXMSMMSMSAMXAXAMSMSAXMAMMASMMSMX | ||||||
|  | MSMSMMMMXXXAAMASAMMSAMSAMXAXXAXAAMAMSMMSSMSMMSSSMSSMMMSAASXSXAXAMXSMSMSMMSASMXMMAMAMXAASXMMXSMMSXSXAMAXSAMAXMAMSAAAMMMSXSMXMAAMMMMSMSXSXAAXX | ||||||
|  | XAAAXAAAXMXMMXAMASXXXSSXMMMMMSSMSMAMAXAAAAXAXAAAAAXAAAMMMMMSMMSMXMAAAAAMXMMMASXSSSSMMMMXAASXSAASASMXMSMMASMMSSMSSMXSAAAAXXSMMMMXAAAMAMXMSSMM | ||||||
|  | SMSMMSSXSASXMMSMMMMSSXMASAMXMAAMMMMSXMSSSMSMMMSMMSMMMSSMSMAXMMAMASMSMSMSASXMMMAAAAMXMASMSMMASMMMMMAAXXASAMAAXXAMMMMSMSMMSAMXSSXSMSSXMAAMMMAM | ||||||
|  | XMAMXXXMAMAASAMAAAAMAXXAMASAMSSMASMMAXMAMXSMSMXXAXASAAMXAMSSMMAXMMAAAAASAXAAXMMMMAMSXAXXXAMXMXAAMXSMMSAMXMMMSMMMAAMXMMMXMAMASMAXXAMAXSXSXSAM | ||||||
|  | XMAMMMASMMMXMASXSMSSMMMSSMSMXMMMMSASXMMMMMXAAAXMAXAMXXSMMMMAMSSSSMSMSMXMSMSMMMXMMXAXMASMSMMAMSSSSMAMAXMXSXMASASMSXSAXMAXSAMXSMMMSSSMMMMMMSAS | ||||||
|  | AMSSMSAMXSXMMAMAXMAXAAAAAAMXAAASMSMMXSAMAAMSMSSSSMAMSXSASXMAMXMAXAAMXMXAAMAMXMAXSMXSAMAAAASXMAAMXXAMSMSAXAMAMMMMAASMSMXMMAMAMAAAAMAXAMASAMXX | ||||||
|  | XAAAXMASAAAXMSXMXMASXMSMMMMMSXMXAMXAXMASASAXAXAAAXSMMASAMASMSMMAMMMMASMMMXAXAMXMXAAAMAMXMXSMMMSMMMMMXAMXSSMAMAAXMMMMAMAMXMMASMMMSSSMXSASXXXA | ||||||
|  | XSMSMSAMXSSMSMSMAMASAAMXSAXXMMSSXMMSMSAMAMMMSMMMMSMAMAMAMMMXAMMXSXXSASAMSSSSSSSXMMMSMXMXMAMASAMXAASAMAMAXXSAMSSSXMASMSXSAMSAMAAMAAASXMASXMSS | ||||||
|  | XMAXAMXMXAMXAAAMSMMMMMSASAMAAAAAAXXAAXAMXMXAMAMXXAXAMMSXXMXMAMSAMXXMAMAMAAXAAAXAMXAXAMMSMASASMXSXXXAXMMSSMMXXAAXMMMMAAAXAMMASMMMMSSMMMAMAMAA | ||||||
|  | MMAMAMXSXMXSMMSAMAXXSSMASMSSMMSSMMMMSMSSSMMMSMMMSMMSAMXMXMMSMSXSXMASXSSMMMMMMMMSAMXSMSAAMMMXSAXSSSSSMXAAXMAMMMMMMASMMMSXSMSAMMAXAMAAAMASMMMA | ||||||
|  | ASAXAMXXAMMXMMXASAMXMAMAMXAAXAAAMAMAAAXAAXAXAXAMAAXMXSAMAXMAMXAXSAXMAXXAXXAAXXAXAMXXAMMSSSMMMXMXAXAMXMMSMMSMSAMASASAMAMAMXMAXSSMMMMMMSASXMXM | ||||||
|  | MSMSXXASMMAAMAMXMXXXXXMAXMXSMMSMSAXSXSMXMSSSMXSSMXMAAXASAMSMSMSMXMSMSMSXMASMSMASMMXMMMAMAAASXSMMXMXMSMAAAXAMXASMSASMMAXMASMSMAAASMSSXMXXAMMX | ||||||
|  | ASAAAXXMAMXSSSXXXMMSMXXXSSXXXXMMSAXMAMXMXXMAMAXAMXSMMSAMMMXXXAMSMASAMXAXAXMAAXMXMASAXMXSSSXMAMMAASMMMMSSSMASXXMMMAMXMASMXMAMMSMMSAAMXMAXSMSX | ||||||
|  | MMMMSAMMAXXAAASMASASXAXSAMXSSSMMMSAMXSXSMMMSMMSAMAAAMMXMMAMSMSAAMMMAMAMXSXMSAMXMXMAMMXXMAMMMSMASXXAAXXAAXMAMXXSAMXMAMSMMAMXMAXMAMMMMAMMSMAMX | ||||||
|  | XAXAXMASASMMMMAMAMSMMMMSAMASASXXAMXSAMMAAMAAMXSAMMMSMAXXMAMXAMXMSXSAMAXAXXMASMXMAMAXSXSMMMAMAXMXASXMMMMMMSSMMMSXSAMAXMASXMAMXSMSSMXSXXMAMAMM | ||||||
|  | SAMXSXMMASXSXXMMSMXXASASXMXMAMXMMMXMASMSMMXMSASAMXXAAXMXSSSMXMMSMMSMSAMXAXMAMMMSSSSMXAAXXSSSMXXMMMAAXAAXMAMAAAMXSASMXSAMMSMSMAAAAXAMMSSXSMSS | ||||||
|  | MXMASMSMMMAXMXXXMASMMMMSAMXMAMMSAMMMXMAMASXSMASMSSXMASMXXAAXAXXAAMXMXXXXSAMASAAMXAAMMMMXXXMAXSMSXSSMMSASMASMSMSAXAMXMMASAAXAASMSSMXSAXMASAAM | ||||||
|  | MAMMMXAAXMSMSMSXMAMAAXXSXMASAXASASAAMMMMAMMAMXMAMXAXMAMMMSMMMMSSSMAMMSMMAMSASMSSMSMMXAXMMMSMMSAAAAXAXXAXXMMAAAMAMSSSXMSMMXSMXMAMXAXMAMMSSMMS | ||||||
|  | SXSSSSSSMAMAAXSAMXSSMMMMXSAXMMXXAMMAAAAMASAMSSMXMSXMMMAXMAXAAAXMAXASMSXAAXMMSAAXAAAMSMMASASAAXXXSMMMMMSMSMMSMMMAMAAAAMMAXMAXAMAMMMMXMAMAMAAX | ||||||
|  | AAAAAAAAMAMSMMSAMAMXMXMXAMSMSXSMXMXMSXMSAXMXAAXMMSMSXMMXSASXXMMSAMXXXMASXSXAMMMSSSSMXAASMASMMSMMAXXAAXAAXXAMAXSXSMSMMMMAMSAMMSXMAXSSMMSASMMS | ||||||
|  | MMMAMMMSMMMXSAMAMASAMAMMMSXXSAAMXMAXAXMMMSMMSSMMMMAMAASXSASMMSAMXSMMAXXMASMMSMAXAMXMSAMMMAMASAXSAMSMSSMSMMMSMMSXMAXXXXMAMXMMXAMMSMXAAXSAMMSM | ||||||
|  | XXAMXXXMAXSSMMSSMXSASASASAMAMSMMASASMMMAMXXAAAXSAMAMSMAAMSMAAMASAAASASAMXMASAMMSSMAMXMASMXSMMAMSAMXAAMMAASAAAAMAXSSMMMSASAMXXXSAMSSMMMMAMMXM | ||||||
|  | MSMMMMMXSMMAAMAMSAXMMMMXSAMSMMMSMAASXAMSMMMSSMMSXSAMAMMXMAXMMMAMXSMMMXXMASXSASAAAMXMAXSXSAAXMXMXMXMMMSSSSMASMMMMMXAXAAMXSASMSMMMSAXAASXMMMAX | ||||||
|  | XAASMMSAAASXMMAXMMMMSSMMSXMAAAMAAMAMXXXMASAMAXAXMMMSASXMMMSMSMMMAXAXXMASASXSMMMXSMSSSMMAMXMSXMMMMMXAXXXMAMAMASAASMMMSSSMSMMAMAASMMSSXXAAMXMX | ||||||
|  | MSSMAAMSSMMXXSMXSXSAAAXAMMMMXMMMSMSXSMMSAMASXMSSMSXSMMAMAMSASXSMSSSMXSAMASMSMAXMAAAAAAMMMMXMAMSAAAXMMMMSMMMSAMAMXAAAAXAASXMSMSMSXMAXAMSMMASM | ||||||
|  | AXMAMMMXMASXMASASAAMSXMAXSASMSSXXAXMMAAMASAMAAAAXSASXSXMAMMAMMSAAAAAXMAMSMMXSASXMMMSMSMAAXAXXMAXSXMAAAAAXAXMMMSSSSMMSSMMMAXMAXAXXMASMMXAMAXA | ||||||
|  | MMAAMXMAMAXXSASMMSMXMXSXMMAXAAAXMSXAMMMMMMMMMMMSMMAMASMSSMMSMAMXMXMXMMAMMASMMMMXAAAXXMXSSSSSMXMMMASMSSSSSMSAMXMAAXAMXXAASXMMMMSMMSAMXASXMXSS | ||||||
|  | AMSMSXSAMXSMMASXAAXAAAXSXMSMMMMXXXMSXSMXSASXAMXMXMAMAMMMMAXAXMMMMSMSSSSXSAMAAXXSSMSSMSMMAAXXXASMMAMAAAAXAMSAMXMMMMXXASXMSMSXMAXSAMXSMMSASAAM | ||||||
|  | SMAAXASXSAAAMXMMMSMMMMSMSAMXXAXMMXAXAMXXMAMMMMAMASAMASAAXMMMMXMAMAMAAAAAMMMSMMAMAAAAMAAMMMMMSMSAMXMMMMMSMMSXMXAAAMMMMSASMMAXMASMXSAMXXSAMMSM | ||||||
|  | ASMMMMMAMMSMMASMAAAXXXAMSMSSSMXMAMSMMMSSMAMAAMXSASASASMSSXSXAASMSMSSMMMMMXXASXMSSMMSSSMMXXAASXSAMXXXAXXXAAXAMMSMSAAMXMMXAASMSMMAAMXSAXMASXMA | ||||||
|  | MAMSSXMAMXXAMAXMMSSMAMXXXAXMAMAMXAXAAAAAXAMMXXXMAMAMAXAMMAMASXMAAXAXSXXXAXMAXSAAXXAXAAASMMSXSASXSSXSMSMSMMXAMXAAXXMXAMXSSMMMAAMMMSXMMXSSMASX | ||||||
|  | XMSAAMSMSSSSMSMSAAAXXSMMMSMXAMMSMAMSMMSSSMSMSAMXSMSMSMASMMMAMMMSMMMSXSMMSSMMMMMMSMMMMSMMAAXAMAMAMAASAAXMAXSASXXSMAMSMMAAAASXSSMMMSAXAASASAMM | ||||||
|  | SXMMSMAAAAAMAAAMMSMMSXAAAAASMSAXMAMAAMAAAAAASMAAXAXAXSAMAAMASXXMASXSAMXAAAAAXXSAMXSAMXXMMMMAMAMAMMSMSMMSAMSAMAXXMXMASMXSSMMMXAAAASMMMSSMMMSA | ||||||
|  | XXXXXXMSMMMMMMSMXAXMASXMSXMAAMMSSMSSSMXSMMMMMMSAMSMMMMMSSMSXSASXMMSMAMMMSSMMAMXXMASXSAXMAMSXSXSXSXXMAMXMXXMMMAMXAXMAMSAAXMXMASXMMSXXMAMXXMAX | ||||||
							
								
								
									
										20
									
								
								y2024/src/bin/d3.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								y2024/src/bin/d3.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | use std::fs; | ||||||
|  |  | ||||||
|  | use y2024::days::d3; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  |     part2(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/3_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d3::process_part1(&content)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part2() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/3_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d3::process_part2(&content)); | ||||||
|  | } | ||||||
							
								
								
									
										20
									
								
								y2024/src/bin/d4.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								y2024/src/bin/d4.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | |||||||
|  | use std::fs; | ||||||
|  |  | ||||||
|  | use y2024::days::d4; | ||||||
|  |  | ||||||
|  | fn main() { | ||||||
|  |     part1(); | ||||||
|  |     part2(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part1() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/4_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d4::process_part1(&content)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn part2() { | ||||||
|  |     let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |     let content = fs::read_to_string(format!("{root}/resources/4_input.txt")).unwrap(); | ||||||
|  |     println!("{}", d4::process_part2(&content)); | ||||||
|  | } | ||||||
							
								
								
									
										98
									
								
								y2024/src/days/d3.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								y2024/src/days/d3.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | |||||||
|  | use regex::Regex; | ||||||
|  |  | ||||||
|  | pub fn process_part1(input: &str) -> i32 { | ||||||
|  |     input | ||||||
|  |         .lines() | ||||||
|  |         .map(extract_mul_pairs) | ||||||
|  |         .map(|pairs| pairs.iter().map(|(a, b)| a * b).sum::<i32>()) | ||||||
|  |         .sum() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Could use this regex but wouldn't know how to solve part 2 | ||||||
|  | // /mul\([0-9]{1,3},[0-9]{1,3}\)/g | ||||||
|  | // /don't\(\).*do\(\)/g would select anything between first don't() and last do() | ||||||
|  | // not sure how to fix, invert and combine this | ||||||
|  | fn extract_mul_pairs(line: &str) -> Vec<(i32, i32)> { | ||||||
|  |     let reg = Regex::new(r"mul\([0-9]{1,3},[0-9]{1,3}\)").unwrap(); | ||||||
|  |     reg.find_iter(line) | ||||||
|  |         .map(|m| { | ||||||
|  |             let match_str = m.as_str(); | ||||||
|  |             let (a, b) = match_str[4..match_str.len() - 1].split_once(",").unwrap(); | ||||||
|  |             let a = a.parse::<i32>().unwrap(); | ||||||
|  |             let b = b.parse::<i32>().unwrap(); | ||||||
|  |             (a, b) | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<(i32, i32)>>() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn extract_mul_pairs_dont(line: &str) -> Vec<(i32, i32)> { | ||||||
|  |     let reg = Regex::new(r"(mul\([0-9]{1,3},[0-9]{1,3}\))|(don't\(\)|do\(\))").unwrap(); | ||||||
|  |     let mut enabled = true; | ||||||
|  |     reg.find_iter(line) | ||||||
|  |         .map(|m| { | ||||||
|  |             let match_str = m.as_str(); | ||||||
|  |             if match_str == "don't()" { | ||||||
|  |                 enabled = false; | ||||||
|  |             } else if match_str == "do()" { | ||||||
|  |                 enabled = true; | ||||||
|  |             } | ||||||
|  |             if !["don't()", "do()"].contains(&match_str) && enabled { | ||||||
|  |                 let (a, b) = match_str[4..match_str.len() - 1].split_once(",").unwrap(); | ||||||
|  |                 let a = a.parse::<i32>().unwrap(); | ||||||
|  |                 let b = b.parse::<i32>().unwrap(); | ||||||
|  |                 (a, b) | ||||||
|  |             } else { | ||||||
|  |                 (0, 0) | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<(i32, i32)>>() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part2(input: &str) -> i32 { | ||||||
|  |     let input = input.lines().collect::<Vec<&str>>().join(""); | ||||||
|  |     extract_mul_pairs_dont(&input) | ||||||
|  |         .into_iter() | ||||||
|  |         .map(|(a, b)| a * b) | ||||||
|  |         .sum() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use std::fs; | ||||||
|  |  | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     const INPUT: &str = | ||||||
|  |         "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))mul( 1, 3)"; | ||||||
|  |  | ||||||
|  |     const INPUT_2: &str = | ||||||
|  |         "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(INPUT); | ||||||
|  |         assert_eq!(result, 161); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn res1() { | ||||||
|  |         let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |         let content = fs::read_to_string(format!("{root}/resources/3_input.txt")).unwrap(); | ||||||
|  |         let result = process_part1(&content); | ||||||
|  |         assert_eq!(result, 183788984); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part2() { | ||||||
|  |         let result = process_part2(INPUT_2); | ||||||
|  |         assert_eq!(result, 48); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn res2() { | ||||||
|  |         let root = env!("CARGO_MANIFEST_DIR"); | ||||||
|  |         let content = fs::read_to_string(format!("{root}/resources/3_input.txt")).unwrap(); | ||||||
|  |         let result = process_part2(&content); | ||||||
|  |         assert_eq!(result, 62098619); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										164
									
								
								y2024/src/days/d4.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								y2024/src/days/d4.rs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | |||||||
|  | use std::cmp; | ||||||
|  |  | ||||||
|  | use utils::grid::Grid; | ||||||
|  |  | ||||||
|  | pub fn process_part1(input: &str) -> i32 { | ||||||
|  |     let grid = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| { | ||||||
|  |             line.chars() | ||||||
|  |                 .map(|char| char.to_string()) | ||||||
|  |                 .collect::<Vec<String>>() | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<Vec<String>>>(); | ||||||
|  |     let mut grid = Grid::new(grid).unwrap(); | ||||||
|  |     let mut res = 0; | ||||||
|  |     for row in &grid.rows { | ||||||
|  |         let row = row.join(""); | ||||||
|  |         res += row.matches("XMAS").count(); | ||||||
|  |         res += row.matches("SAMX").count(); | ||||||
|  |     } | ||||||
|  |     for diag_grave in grid.get_diagonals_grave() { | ||||||
|  |         let diag_grave = diag_grave.join(""); | ||||||
|  |         res += diag_grave.matches("XMAS").count(); | ||||||
|  |         res += diag_grave.matches("SAMX").count(); | ||||||
|  |     } | ||||||
|  |     for diag_aigu in grid.get_diagonals_aigu() { | ||||||
|  |         let diag_aigu = diag_aigu.join(""); | ||||||
|  |         res += diag_aigu.matches("XMAS").count(); | ||||||
|  |         res += diag_aigu.matches("SAMX").count(); | ||||||
|  |     } | ||||||
|  |     for col in grid.rotate_90().rows { | ||||||
|  |         let col = col.join(""); | ||||||
|  |         res += col.matches("XMAS").count(); | ||||||
|  |         res += col.matches("SAMX").count(); | ||||||
|  |     } | ||||||
|  |     res.try_into().unwrap() | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn process_part2(input: &str) -> i32 { | ||||||
|  |     let grid = input | ||||||
|  |         .lines() | ||||||
|  |         .map(|line| { | ||||||
|  |             line.chars() | ||||||
|  |                 .map(|char| char.to_string()) | ||||||
|  |                 .collect::<Vec<String>>() | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<Vec<String>>>(); | ||||||
|  |     let grid = Grid::new(grid).unwrap(); | ||||||
|  |     let mut res = 0; | ||||||
|  |     // Irrelevant as this finds + not x | ||||||
|  |     // But actually helpful as I can just create diagonals, left and right pad to create a square | ||||||
|  |     // grid and apply this | ||||||
|  |     //for (row_idx, row) in grid.rows.iter().enumerate() { | ||||||
|  |     //    if row_idx == 0 || row_idx == grid.rows.len() - 1 { | ||||||
|  |     //        continue; | ||||||
|  |     //    } | ||||||
|  |     //    let row = row.join(""); | ||||||
|  |     //    for (match_idx, _) in row.match_indices("MAS") { | ||||||
|  |     //        let above = grid.rows[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |     //        let below = grid.rows[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |     //        if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |     //            res += 1; | ||||||
|  |     //        } | ||||||
|  |     //    } | ||||||
|  |     //    for (match_idx, _) in row.match_indices("SAM") { | ||||||
|  |     //        let above = grid.rows[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |     //        let below = grid.rows[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |     //        if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |     //            res += 1; | ||||||
|  |     //        } | ||||||
|  |     //    } | ||||||
|  |     //} | ||||||
|  |     let diagonals = grid.get_diagonals_grave(); | ||||||
|  |     // new width is as long as the longest diagonal | ||||||
|  |     // the diagonal length goes from 1..min(grid width, grid height) | ||||||
|  |     // then pad on each side by difference / 2 | ||||||
|  |     let new_width = cmp::min(grid.width as usize, grid.rows.len()); | ||||||
|  |     let mut even_grid = Vec::new(); | ||||||
|  |     let mut odd_grid = Vec::new(); | ||||||
|  |     for diagonal in diagonals { | ||||||
|  |         let diagonal_length = diagonal.len(); | ||||||
|  |         let pad = (new_width - diagonal_length) / 2; | ||||||
|  |         let new_row = [ | ||||||
|  |             vec!["#".to_string(); pad], | ||||||
|  |             diagonal, | ||||||
|  |             vec!["#".to_string(); pad], | ||||||
|  |         ] | ||||||
|  |         .concat(); | ||||||
|  |         if diagonal_length % 2 == 0 { | ||||||
|  |             even_grid.push(new_row); | ||||||
|  |         } else { | ||||||
|  |             odd_grid.push(new_row); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     for (row_idx, row) in even_grid.iter().enumerate() { | ||||||
|  |         if row_idx == 0 || row_idx == even_grid.len() - 1 { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         let row = row.join(""); | ||||||
|  |         for (match_idx, _) in row.match_indices("MAS") { | ||||||
|  |             let above = even_grid[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |             let below = even_grid[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |             if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |                 res += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         for (match_idx, _) in row.match_indices("SAM") { | ||||||
|  |             let above = even_grid[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |             let below = even_grid[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |             if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |                 res += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     for (row_idx, row) in odd_grid.iter().enumerate() { | ||||||
|  |         if row_idx == 0 || row_idx == odd_grid.len() - 1 { | ||||||
|  |             continue; | ||||||
|  |         } | ||||||
|  |         let row = row.join(""); | ||||||
|  |         for (match_idx, _) in row.match_indices("MAS") { | ||||||
|  |             let above = odd_grid[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |             let below = odd_grid[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |             if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |                 res += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         for (match_idx, _) in row.match_indices("SAM") { | ||||||
|  |             let above = odd_grid[row_idx - 1][match_idx + 1].clone(); | ||||||
|  |             let below = odd_grid[row_idx + 1][match_idx + 1].clone(); | ||||||
|  |             if (above == "M" && below == "S") || (above == "S" && below == "M") { | ||||||
|  |                 res += 1; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     res | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #[cfg(test)] | ||||||
|  | mod tests { | ||||||
|  |     use super::*; | ||||||
|  |  | ||||||
|  |     const INPUT: &str = "MMMSXXMASM | ||||||
|  | MSAMXMSMSA | ||||||
|  | AMXSXMAAMM | ||||||
|  | MSAMASMSMX | ||||||
|  | XMASAMXAMM | ||||||
|  | XXAMMXXAMA | ||||||
|  | SMSMSASXSS | ||||||
|  | SAXAMASAAA | ||||||
|  | MAMMMXMMMM | ||||||
|  | MXMXAXMASX"; | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part1() { | ||||||
|  |         let result = process_part1(INPUT); | ||||||
|  |         assert_eq!(result, 18); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     #[test] | ||||||
|  |     fn part2() { | ||||||
|  |         let result = process_part2(INPUT); | ||||||
|  |         assert_eq!(result, 9); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,3 +1,7 @@ | |||||||
| pub mod d1; | pub mod d1; | ||||||
|  |  | ||||||
| pub mod d2; | pub mod d2; | ||||||
|  |  | ||||||
|  | pub mod d3; | ||||||
|  |  | ||||||
|  | pub mod d4; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user