A => 1/main.rs +47 -0
@@ 1,47 @@
+use std::io::Read;
+
+fn solve_a(input: &str) -> i32 {
+ input.chars().filter(|c| *c == '(').count() as i32 -
+ input.chars().filter(|c| *c == ')').count() as i32
+}
+
+fn solve_b(input: &str) -> usize {
+ let mut level = 0;
+ for (i, c) in input.chars().enumerate() {
+ if c == '(' {
+ level += 1;
+ } else {
+ level -= 1;
+ }
+ if level < 0 {
+ return i+1
+ }
+ }
+ unreachable!();
+}
+
+fn main() {
+ let mut buf = String::new();
+ std::io::stdin().read_to_string(&mut buf).unwrap();
+ println!("{}", solve_a(buf.trim()));
+ println!("{}", solve_b(buf.trim()));
+}
+
+#[test]
+fn solve_a_test() {
+ assert_eq!(0, solve_a("(())"));
+ assert_eq!(0, solve_a("()()"));
+ assert_eq!(3, solve_a("((("));
+ assert_eq!(3, solve_a("(()(()("));
+ assert_eq!(3, solve_a("))((((("));
+ assert_eq!(-1, solve_a("())"));
+ assert_eq!(-1, solve_a("))("));
+ assert_eq!(-3, solve_a(")))"));
+ assert_eq!(-3, solve_a(")())())"));
+}
+
+#[test]
+fn solve_b_test() {
+ assert_eq!(1, solve_b(")"));
+ assert_eq!(5, solve_b("()())"));
+}
A => 2/main.rs +61 -0
@@ 1,61 @@
+use std::io::{BufRead,BufReader};
+
+#[derive(PartialEq, Debug)]
+struct Present {
+ w: i32,
+ h: i32,
+ l: i32
+}
+
+impl Present {
+
+ fn new(w: i32, h: i32, l: i32) -> Present {
+ Present{w, h, l}
+ }
+
+ fn area(&self) -> i32 {
+ let a = 2 * self.l * self.w;
+ let b = 2 * self.w * self.h;
+ let c = 2 * self.h * self.l;
+ let smallest = if a < b { a } else { b };
+ let smallest = if smallest < c { smallest } else { c };
+ a + b + c + smallest / 2
+ }
+
+ fn ribbon(&self) -> i32 {
+ let bow = self.w * self.h * self.l;
+ let a = (self.l + self.w) * 2;
+ let b = (self.w + self.h) * 2;
+ let c = (self.h + self.l) * 2;
+ let smallest = if a < b { a } else { b };
+ let smallest = if smallest < c { smallest } else { c };
+ smallest + bow
+ }
+}
+
+fn parse(input: &str) -> Present {
+ let r : Vec<i32> = input.split('x').map(|s| s.parse().unwrap()).collect();
+ Present::new(r[0], r[1], r[2])
+}
+
+fn main() {
+ let r = BufReader::new(std::io::stdin());
+ let presents : Vec<Present> = r.lines().map(|r| parse(&r.unwrap())).collect();
+
+ let area : i32 = presents.iter().map(Present::area).sum();
+ println!("{}", area);
+ let ribbon : i32 = presents.iter().map(Present::ribbon).sum();
+ println!("{}", ribbon);
+}
+
+#[test]
+fn area_test() {
+ assert_eq!(58, Present::new(2,3,4).area());
+ assert_eq!(43, Present::new(1,1,10).area());
+}
+
+#[test]
+fn parse_test() {
+ assert_eq!(Present::new(2,3,4), parse("2x3x4"));
+ assert_eq!(Present::new(1,1,10), parse("1x1x10"));
+}
A => 3/main.rs +91 -0
@@ 1,91 @@
+use std::collections::HashSet;
+use std::io::Read;
+
+#[derive(Clone,Hash,PartialEq,Eq,Debug)]
+struct Pos {
+ x: i32,
+ y: i32
+}
+
+#[derive(Clone, Copy)]
+enum Direction {
+ Up, Down, Left, Right
+}
+
+impl Pos {
+ fn move_by(&self, d: Direction) -> Pos {
+ match d {
+ Direction::Up => Pos{x: self.x, y: self.y+1 },
+ Direction::Down => Pos{x: self.x, y: self.y-1 },
+ Direction::Left => Pos{x: self.x-1, y: self.y },
+ Direction::Right => Pos{x: self.x+1, y: self.y },
+ }
+ }
+}
+
+fn parse(c: char) -> Direction {
+ match c {
+ '^' => Direction::Up,
+ 'v' => Direction::Down,
+ '>' => Direction::Right,
+ '<' => Direction::Left,
+ _ => unreachable!(),
+ }
+}
+
+fn solve_a(directions: &[Direction]) -> usize {
+ let mut pos = Pos{x: 0, y: 0};
+ solve(directions, |_, d, s| { pos = pos.move_by(d); s.insert(pos.clone()); })
+}
+
+fn solve_b(directions: &[Direction]) -> usize {
+ let mut pos = Pos{x: 0, y: 0};
+ let mut robo = Pos{x: 0, y: 0};
+ let f = |i, d, s: &mut HashSet<Pos>| {
+ if i % 2 == 0 {
+ pos = pos.move_by(d);
+ s.insert(pos.clone());
+ } else {
+ robo = robo.move_by(d);
+ s.insert(robo.clone());
+ }
+ };
+ solve(directions, f)
+}
+
+fn solve<F>(directions: &[Direction], mut f: F) -> usize
+ where F: FnMut(usize, Direction, &mut HashSet<Pos>) -> () {
+ let mut seen = HashSet::new();
+ seen.insert(Pos{x: 0, y: 0});
+ directions.iter().enumerate().for_each(|(i, d)| f(i, *d, &mut seen));
+ seen.len()
+}
+
+fn main() {
+ let mut buf = String::new();
+ std::io::stdin().read_to_string(&mut buf).unwrap();
+ let directions : Vec<Direction> = buf.trim().chars().map(parse).collect();
+ let a = solve_a(&directions);
+ println!("{}", a);
+ let b = solve_b(&directions);
+ println!("{}", b);
+}
+
+#[test]
+fn solve_a_test() {
+ assert_eq!(2, solve_a(&[Direction::Right]));
+ assert_eq!(4, solve_a(&[Direction::Up,Direction::Right,Direction::Down,Direction::Left]));
+ assert_eq!(2, solve_a(&[
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down,
+ Direction::Up,Direction::Down]));
+}
+
+#[test]
+fn solve_b_test() {
+ assert_eq!(3, solve_b(&[Direction::Up, Direction::Down]));
+}
A => 5/main.rs +65 -0
@@ 1,65 @@
+use std::io::BufRead;
+
+static NEEDED_VOVELS : &str = "aeiou";
+
+fn vovels(s: &str) -> bool {
+ s.chars().filter(|c| NEEDED_VOVELS.contains(*c)).count() >= 3
+}
+
+fn row(s: &str) -> bool {
+ s.chars().zip(s.chars().skip(1)).any(|(a,b)| a == b)
+}
+
+static FORBIDEN_SUBSTRINGS : &[&str] = &["ab", "cd", "pq", "xy"];
+
+fn forbiden(s: &str) -> bool {
+ FORBIDEN_SUBSTRINGS.iter().all(|x| !s.contains(x))
+}
+
+fn is_nice_string(s: &str) -> bool {
+ vovels(s) && row(s) && forbiden(s)
+}
+
+fn three(s: &str) -> bool {
+ s.chars().zip(s.chars().skip(2)).any(|(a,b)| a == b)
+}
+
+fn pair(s: &str) -> bool {
+ let v : Vec<char> = s.chars().collect();
+ for w in v.windows(2) {
+ let needle : String = w.iter().collect();
+ if s.matches(&needle).count() > 1 {
+ return true
+ }
+ }
+ false
+}
+
+fn is_nice_string_b(s: &str) -> bool {
+ three(s) && pair(s)
+}
+
+fn main() {
+ let lines : Vec<String> = std::io::BufReader::new(std::io::stdin())
+ .lines()
+ .map(|s| s.unwrap()).collect();
+ let nice = lines
+ .iter()
+ .filter(|s| is_nice_string(s))
+ .count();
+ println!("{}", nice);
+ let nice_b = lines
+ .iter()
+ .filter(|s| is_nice_string_b(s))
+ .count();
+ println!("{}", nice_b);
+}
+
+#[test]
+fn is_nice_string_test() {
+ assert!(is_nice_string("ugknbfddgicrmopn"));
+ assert!(is_nice_string("aaa"));
+ assert!(!is_nice_string("jchzalrnumimnmhp"));
+ assert!(!is_nice_string("haegwjzuvuyypxyu"));
+ assert!(!is_nice_string("dvszwmarrgswjxmb"));
+}
A => 6/main.rs +94 -0
@@ 1,94 @@
+use std::io::BufRead;
+
+const SIZE: usize = 1000;
+
+fn new_board<T: Copy>(default: T) -> [[T; SIZE]; SIZE] {
+ [[default; SIZE]; SIZE]
+}
+
+fn count<T, F: Fn(&T) -> bool>(b: &[[T; SIZE]; SIZE], f: F) -> usize {
+ b.iter().map(|r| r.iter().filter(|x| f(*x)).count()).sum()
+}
+
+fn set<T: Copy, F: Fn(&T) -> T>(b: &mut [[T; SIZE]; SIZE], first: (usize, usize), last: (usize, usize), f: F) {
+ for x in first.0..(last.0+1) {
+ for y in first.1..(last.1+1) {
+ b[x][y] = f(&b[x][y]);// value;
+ }
+ }
+}
+
+fn toggle<T, F: Fn(&T) -> T>(b: &mut [[T; SIZE]; SIZE], first: (usize, usize), last: (usize, usize), f: F) {
+ for x in first.0..(last.0+1) {
+ for y in first.1..(last.1+1) {
+ b[x][y] = f(&b[x][y]);// !b[x][y];
+ }
+ }
+}
+
+fn parse_pair(s: &str) -> (usize, usize) {
+ let s : Vec<&str> = s.split(',').collect();
+ (s[0].parse::<usize>().unwrap(), s[1].parse::<usize>().unwrap())
+}
+
+fn exec<T: Copy, F1: Fn(&T) -> T, F2: Fn(&T) -> T, F3: Fn(&T) -> T>(mut b: &mut [[T; SIZE]; SIZE], s: &str, on: F1, off: F2, tog: F3) {
+ if s.starts_with("turn on ") {
+ let tmp : Vec<&str> = s.split(" ").collect();
+ let start = parse_pair(tmp[2]);
+ let last = parse_pair(tmp[4]);
+ set(&mut b, start, last, on);
+ } else if s.starts_with("turn off ") {
+ let tmp : Vec<&str> = s.split(" ").collect();
+ let start = parse_pair(tmp[2]);
+ let last = parse_pair(tmp[4]);
+ set(&mut b, start, last, off);
+ } else if s.starts_with("toggle ") {
+ let tmp : Vec<&str> = s.split(" ").collect();
+ let start = parse_pair(tmp[1]);
+ let last = parse_pair(tmp[3]);
+ toggle(&mut b, start, last, tog);
+ }
+}
+
+fn main() {
+ let lines : Result<Vec<String>,_> = std::io::BufReader::new(std::io::stdin()).lines().collect();
+ let lines = lines.unwrap();
+ let mut b = new_board::<bool>(false);
+ for l in &lines {
+ exec(&mut b, &l, |_| true, |_| false, |x| !x);
+ }
+ println!("{}", count(&b, |b| *b));
+ let mut b = new_board::<u32>(0);
+ for l in lines {
+ exec(&mut b, &l, |v| v+1, |v| v.saturating_sub(1), |v| v+2);
+ }
+ let sum : u32 = b.iter().map(|r| r.iter().sum::<u32>()).sum();
+ println!("{}", sum);
+}
+
+#[test]
+fn test_empty_board() {
+ assert_eq!(0, count(&new_board::<bool>(false)));
+}
+
+#[test]
+fn test_1() {
+ let mut b = new_board::<bool>(false);
+ set(&mut b, (0, 0), (999, 999), true);
+ assert_eq!(1000*1000, count(&b));
+}
+
+#[test]
+fn test_2() {
+ let mut b = new_board::<bool>(false);
+ toggle(&mut b, (0, 0), (999, 0), |b| !b);
+ assert_eq!(1000, count(&b));
+}
+
+#[test]
+fn test_3() {
+ let mut b = new_board::<bool>(false);
+ set(&mut b, (0, 0), (999, 999), true);
+ set(&mut b, (499,499), (500, 500), false);
+ assert_eq!(1000*1000-4, count(&b));
+}
A => day7/Cargo.toml +11 -0
@@ 1,11 @@
+[package]
+name = "day7"
+version = "0.1.0"
+authors = ["Tomasz Kłak <tomasz@tomaszklak.pl>"]
+edition = "2018"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+regex = "1"
+lazy_static = "1.4"
A => day7/input +339 -0
@@ 1,339 @@
+bn RSHIFT 2 -> bo
+lf RSHIFT 1 -> ly
+fo RSHIFT 3 -> fq
+cj OR cp -> cq
+fo OR fz -> ga
+t OR s -> u
+lx -> a
+NOT ax -> ay
+he RSHIFT 2 -> hf
+lf OR lq -> lr
+lr AND lt -> lu
+dy OR ej -> ek
+1 AND cx -> cy
+hb LSHIFT 1 -> hv
+1 AND bh -> bi
+ih AND ij -> ik
+c LSHIFT 1 -> t
+ea AND eb -> ed
+km OR kn -> ko
+NOT bw -> bx
+ci OR ct -> cu
+NOT p -> q
+lw OR lv -> lx
+NOT lo -> lp
+fp OR fv -> fw
+o AND q -> r
+dh AND dj -> dk
+ap LSHIFT 1 -> bj
+bk LSHIFT 1 -> ce
+NOT ii -> ij
+gh OR gi -> gj
+kk RSHIFT 1 -> ld
+lc LSHIFT 1 -> lw
+lb OR la -> lc
+1 AND am -> an
+gn AND gp -> gq
+lf RSHIFT 3 -> lh
+e OR f -> g
+lg AND lm -> lo
+ci RSHIFT 1 -> db
+cf LSHIFT 1 -> cz
+bn RSHIFT 1 -> cg
+et AND fe -> fg
+is OR it -> iu
+kw AND ky -> kz
+ck AND cl -> cn
+bj OR bi -> bk
+gj RSHIFT 1 -> hc
+iu AND jf -> jh
+NOT bs -> bt
+kk OR kv -> kw
+ks AND ku -> kv
+hz OR ik -> il
+b RSHIFT 1 -> v
+iu RSHIFT 1 -> jn
+fo RSHIFT 5 -> fr
+be AND bg -> bh
+ga AND gc -> gd
+hf OR hl -> hm
+ld OR le -> lf
+as RSHIFT 5 -> av
+fm OR fn -> fo
+hm AND ho -> hp
+lg OR lm -> ln
+NOT kx -> ky
+kk RSHIFT 3 -> km
+ek AND em -> en
+NOT ft -> fu
+NOT jh -> ji
+jn OR jo -> jp
+gj AND gu -> gw
+d AND j -> l
+et RSHIFT 1 -> fm
+jq OR jw -> jx
+ep OR eo -> eq
+lv LSHIFT 15 -> lz
+NOT ey -> ez
+jp RSHIFT 2 -> jq
+eg AND ei -> ej
+NOT dm -> dn
+jp AND ka -> kc
+as AND bd -> bf
+fk OR fj -> fl
+dw OR dx -> dy
+lj AND ll -> lm
+ec AND ee -> ef
+fq AND fr -> ft
+NOT kp -> kq
+ki OR kj -> kk
+cz OR cy -> da
+as RSHIFT 3 -> au
+an LSHIFT 15 -> ar
+fj LSHIFT 15 -> fn
+1 AND fi -> fj
+he RSHIFT 1 -> hx
+lf RSHIFT 2 -> lg
+kf LSHIFT 15 -> kj
+dz AND ef -> eh
+ib OR ic -> id
+lf RSHIFT 5 -> li
+bp OR bq -> br
+NOT gs -> gt
+fo RSHIFT 1 -> gh
+bz AND cb -> cc
+ea OR eb -> ec
+lf AND lq -> ls
+NOT l -> m
+hz RSHIFT 3 -> ib
+NOT di -> dj
+NOT lk -> ll
+jp RSHIFT 3 -> jr
+jp RSHIFT 5 -> js
+NOT bf -> bg
+s LSHIFT 15 -> w
+eq LSHIFT 1 -> fk
+jl OR jk -> jm
+hz AND ik -> im
+dz OR ef -> eg
+1 AND gy -> gz
+la LSHIFT 15 -> le
+br AND bt -> bu
+NOT cn -> co
+v OR w -> x
+d OR j -> k
+1 AND gd -> ge
+ia OR ig -> ih
+NOT go -> gp
+NOT ed -> ee
+jq AND jw -> jy
+et OR fe -> ff
+aw AND ay -> az
+ff AND fh -> fi
+ir LSHIFT 1 -> jl
+gg LSHIFT 1 -> ha
+x RSHIFT 2 -> y
+db OR dc -> dd
+bl OR bm -> bn
+ib AND ic -> ie
+x RSHIFT 3 -> z
+lh AND li -> lk
+ce OR cd -> cf
+NOT bb -> bc
+hi AND hk -> hl
+NOT gb -> gc
+1 AND r -> s
+fw AND fy -> fz
+fb AND fd -> fe
+1 AND en -> eo
+z OR aa -> ab
+bi LSHIFT 15 -> bm
+hg OR hh -> hi
+kh LSHIFT 1 -> lb
+cg OR ch -> ci
+1 AND kz -> la
+gf OR ge -> gg
+gj RSHIFT 2 -> gk
+dd RSHIFT 2 -> de
+NOT ls -> lt
+lh OR li -> lj
+jr OR js -> jt
+au AND av -> ax
+0 -> c
+he AND hp -> hr
+id AND if -> ig
+et RSHIFT 5 -> ew
+bp AND bq -> bs
+e AND f -> h
+ly OR lz -> ma
+1 AND lu -> lv
+NOT jd -> je
+ha OR gz -> hb
+dy RSHIFT 1 -> er
+iu RSHIFT 2 -> iv
+NOT hr -> hs
+as RSHIFT 1 -> bl
+kk RSHIFT 2 -> kl
+b AND n -> p
+ln AND lp -> lq
+cj AND cp -> cr
+dl AND dn -> do
+ci RSHIFT 2 -> cj
+as OR bd -> be
+ge LSHIFT 15 -> gi
+hz RSHIFT 5 -> ic
+dv LSHIFT 1 -> ep
+kl OR kr -> ks
+gj OR gu -> gv
+he RSHIFT 5 -> hh
+NOT fg -> fh
+hg AND hh -> hj
+b OR n -> o
+jk LSHIFT 15 -> jo
+gz LSHIFT 15 -> hd
+cy LSHIFT 15 -> dc
+kk RSHIFT 5 -> kn
+ci RSHIFT 3 -> ck
+at OR az -> ba
+iu RSHIFT 3 -> iw
+ko AND kq -> kr
+NOT eh -> ei
+aq OR ar -> as
+iy AND ja -> jb
+dd RSHIFT 3 -> df
+bn RSHIFT 3 -> bp
+1 AND cc -> cd
+at AND az -> bb
+x OR ai -> aj
+kk AND kv -> kx
+ao OR an -> ap
+dy RSHIFT 3 -> ea
+x RSHIFT 1 -> aq
+eu AND fa -> fc
+kl AND kr -> kt
+ia AND ig -> ii
+df AND dg -> di
+NOT fx -> fy
+k AND m -> n
+bn RSHIFT 5 -> bq
+km AND kn -> kp
+dt LSHIFT 15 -> dx
+hz RSHIFT 2 -> ia
+aj AND al -> am
+cd LSHIFT 15 -> ch
+hc OR hd -> he
+he RSHIFT 3 -> hg
+bn OR by -> bz
+NOT kt -> ku
+z AND aa -> ac
+NOT ak -> al
+cu AND cw -> cx
+NOT ie -> if
+dy RSHIFT 2 -> dz
+ip LSHIFT 15 -> it
+de OR dk -> dl
+au OR av -> aw
+jg AND ji -> jj
+ci AND ct -> cv
+dy RSHIFT 5 -> eb
+hx OR hy -> hz
+eu OR fa -> fb
+gj RSHIFT 3 -> gl
+fo AND fz -> gb
+1 AND jj -> jk
+jp OR ka -> kb
+de AND dk -> dm
+ex AND ez -> fa
+df OR dg -> dh
+iv OR jb -> jc
+x RSHIFT 5 -> aa
+NOT hj -> hk
+NOT im -> in
+fl LSHIFT 1 -> gf
+hu LSHIFT 15 -> hy
+iq OR ip -> ir
+iu RSHIFT 5 -> ix
+NOT fc -> fd
+NOT el -> em
+ck OR cl -> cm
+et RSHIFT 3 -> ev
+hw LSHIFT 1 -> iq
+ci RSHIFT 5 -> cl
+iv AND jb -> jd
+dd RSHIFT 5 -> dg
+as RSHIFT 2 -> at
+NOT jy -> jz
+af AND ah -> ai
+1 AND ds -> dt
+jx AND jz -> ka
+da LSHIFT 1 -> du
+fs AND fu -> fv
+jp RSHIFT 1 -> ki
+iw AND ix -> iz
+iw OR ix -> iy
+eo LSHIFT 15 -> es
+ev AND ew -> ey
+ba AND bc -> bd
+fp AND fv -> fx
+jc AND je -> jf
+et RSHIFT 2 -> eu
+kg OR kf -> kh
+iu OR jf -> jg
+er OR es -> et
+fo RSHIFT 2 -> fp
+NOT ca -> cb
+bv AND bx -> by
+u LSHIFT 1 -> ao
+cm AND co -> cp
+y OR ae -> af
+bn AND by -> ca
+1 AND ke -> kf
+jt AND jv -> jw
+fq OR fr -> fs
+dy AND ej -> el
+NOT kc -> kd
+ev OR ew -> ex
+dd OR do -> dp
+NOT cv -> cw
+gr AND gt -> gu
+dd RSHIFT 1 -> dw
+NOT gw -> gx
+NOT iz -> ja
+1 AND io -> ip
+NOT ag -> ah
+b RSHIFT 5 -> f
+NOT cr -> cs
+kb AND kd -> ke
+jr AND js -> ju
+cq AND cs -> ct
+il AND in -> io
+NOT ju -> jv
+du OR dt -> dv
+dd AND do -> dq
+b RSHIFT 2 -> d
+jm LSHIFT 1 -> kg
+NOT dq -> dr
+bo OR bu -> bv
+gk OR gq -> gr
+he OR hp -> hq
+NOT h -> i
+hf AND hl -> hn
+gv AND gx -> gy
+x AND ai -> ak
+bo AND bu -> bw
+hq AND hs -> ht
+hz RSHIFT 1 -> is
+gj RSHIFT 5 -> gm
+g AND i -> j
+gk AND gq -> gs
+dp AND dr -> ds
+b RSHIFT 3 -> e
+gl AND gm -> go
+gl OR gm -> gn
+y AND ae -> ag
+hv OR hu -> hw
+1674 -> b
+ab AND ad -> ae
+NOT ac -> ad
+1 AND ht -> hu
+NOT hn -> ho
A => day7/input2 +339 -0
@@ 1,339 @@
+bn RSHIFT 2 -> bo
+lf RSHIFT 1 -> ly
+fo RSHIFT 3 -> fq
+cj OR cp -> cq
+fo OR fz -> ga
+t OR s -> u
+lx -> a
+NOT ax -> ay
+he RSHIFT 2 -> hf
+lf OR lq -> lr
+lr AND lt -> lu
+dy OR ej -> ek
+1 AND cx -> cy
+hb LSHIFT 1 -> hv
+1 AND bh -> bi
+ih AND ij -> ik
+c LSHIFT 1 -> t
+ea AND eb -> ed
+km OR kn -> ko
+NOT bw -> bx
+ci OR ct -> cu
+NOT p -> q
+lw OR lv -> lx
+NOT lo -> lp
+fp OR fv -> fw
+o AND q -> r
+dh AND dj -> dk
+ap LSHIFT 1 -> bj
+bk LSHIFT 1 -> ce
+NOT ii -> ij
+gh OR gi -> gj
+kk RSHIFT 1 -> ld
+lc LSHIFT 1 -> lw
+lb OR la -> lc
+1 AND am -> an
+gn AND gp -> gq
+lf RSHIFT 3 -> lh
+e OR f -> g
+lg AND lm -> lo
+ci RSHIFT 1 -> db
+cf LSHIFT 1 -> cz
+bn RSHIFT 1 -> cg
+et AND fe -> fg
+is OR it -> iu
+kw AND ky -> kz
+ck AND cl -> cn
+bj OR bi -> bk
+gj RSHIFT 1 -> hc
+iu AND jf -> jh
+NOT bs -> bt
+kk OR kv -> kw
+ks AND ku -> kv
+hz OR ik -> il
+b RSHIFT 1 -> v
+iu RSHIFT 1 -> jn
+fo RSHIFT 5 -> fr
+be AND bg -> bh
+ga AND gc -> gd
+hf OR hl -> hm
+ld OR le -> lf
+as RSHIFT 5 -> av
+fm OR fn -> fo
+hm AND ho -> hp
+lg OR lm -> ln
+NOT kx -> ky
+kk RSHIFT 3 -> km
+ek AND em -> en
+NOT ft -> fu
+NOT jh -> ji
+jn OR jo -> jp
+gj AND gu -> gw
+d AND j -> l
+et RSHIFT 1 -> fm
+jq OR jw -> jx
+ep OR eo -> eq
+lv LSHIFT 15 -> lz
+NOT ey -> ez
+jp RSHIFT 2 -> jq
+eg AND ei -> ej
+NOT dm -> dn
+jp AND ka -> kc
+as AND bd -> bf
+fk OR fj -> fl
+dw OR dx -> dy
+lj AND ll -> lm
+ec AND ee -> ef
+fq AND fr -> ft
+NOT kp -> kq
+ki OR kj -> kk
+cz OR cy -> da
+as RSHIFT 3 -> au
+an LSHIFT 15 -> ar
+fj LSHIFT 15 -> fn
+1 AND fi -> fj
+he RSHIFT 1 -> hx
+lf RSHIFT 2 -> lg
+kf LSHIFT 15 -> kj
+dz AND ef -> eh
+ib OR ic -> id
+lf RSHIFT 5 -> li
+bp OR bq -> br
+NOT gs -> gt
+fo RSHIFT 1 -> gh
+bz AND cb -> cc
+ea OR eb -> ec
+lf AND lq -> ls
+NOT l -> m
+hz RSHIFT 3 -> ib
+NOT di -> dj
+NOT lk -> ll
+jp RSHIFT 3 -> jr
+jp RSHIFT 5 -> js
+NOT bf -> bg
+s LSHIFT 15 -> w
+eq LSHIFT 1 -> fk
+jl OR jk -> jm
+hz AND ik -> im
+dz OR ef -> eg
+1 AND gy -> gz
+la LSHIFT 15 -> le
+br AND bt -> bu
+NOT cn -> co
+v OR w -> x
+d OR j -> k
+1 AND gd -> ge
+ia OR ig -> ih
+NOT go -> gp
+NOT ed -> ee
+jq AND jw -> jy
+et OR fe -> ff
+aw AND ay -> az
+ff AND fh -> fi
+ir LSHIFT 1 -> jl
+gg LSHIFT 1 -> ha
+x RSHIFT 2 -> y
+db OR dc -> dd
+bl OR bm -> bn
+ib AND ic -> ie
+x RSHIFT 3 -> z
+lh AND li -> lk
+ce OR cd -> cf
+NOT bb -> bc
+hi AND hk -> hl
+NOT gb -> gc
+1 AND r -> s
+fw AND fy -> fz
+fb AND fd -> fe
+1 AND en -> eo
+z OR aa -> ab
+bi LSHIFT 15 -> bm
+hg OR hh -> hi
+kh LSHIFT 1 -> lb
+cg OR ch -> ci
+1 AND kz -> la
+gf OR ge -> gg
+gj RSHIFT 2 -> gk
+dd RSHIFT 2 -> de
+NOT ls -> lt
+lh OR li -> lj
+jr OR js -> jt
+au AND av -> ax
+0 -> c
+he AND hp -> hr
+id AND if -> ig
+et RSHIFT 5 -> ew
+bp AND bq -> bs
+e AND f -> h
+ly OR lz -> ma
+1 AND lu -> lv
+NOT jd -> je
+ha OR gz -> hb
+dy RSHIFT 1 -> er
+iu RSHIFT 2 -> iv
+NOT hr -> hs
+as RSHIFT 1 -> bl
+kk RSHIFT 2 -> kl
+b AND n -> p
+ln AND lp -> lq
+cj AND cp -> cr
+dl AND dn -> do
+ci RSHIFT 2 -> cj
+as OR bd -> be
+ge LSHIFT 15 -> gi
+hz RSHIFT 5 -> ic
+dv LSHIFT 1 -> ep
+kl OR kr -> ks
+gj OR gu -> gv
+he RSHIFT 5 -> hh
+NOT fg -> fh
+hg AND hh -> hj
+b OR n -> o
+jk LSHIFT 15 -> jo
+gz LSHIFT 15 -> hd
+cy LSHIFT 15 -> dc
+kk RSHIFT 5 -> kn
+ci RSHIFT 3 -> ck
+at OR az -> ba
+iu RSHIFT 3 -> iw
+ko AND kq -> kr
+NOT eh -> ei
+aq OR ar -> as
+iy AND ja -> jb
+dd RSHIFT 3 -> df
+bn RSHIFT 3 -> bp
+1 AND cc -> cd
+at AND az -> bb
+x OR ai -> aj
+kk AND kv -> kx
+ao OR an -> ap
+dy RSHIFT 3 -> ea
+x RSHIFT 1 -> aq
+eu AND fa -> fc
+kl AND kr -> kt
+ia AND ig -> ii
+df AND dg -> di
+NOT fx -> fy
+k AND m -> n
+bn RSHIFT 5 -> bq
+km AND kn -> kp
+dt LSHIFT 15 -> dx
+hz RSHIFT 2 -> ia
+aj AND al -> am
+cd LSHIFT 15 -> ch
+hc OR hd -> he
+he RSHIFT 3 -> hg
+bn OR by -> bz
+NOT kt -> ku
+z AND aa -> ac
+NOT ak -> al
+cu AND cw -> cx
+NOT ie -> if
+dy RSHIFT 2 -> dz
+ip LSHIFT 15 -> it
+de OR dk -> dl
+au OR av -> aw
+jg AND ji -> jj
+ci AND ct -> cv
+dy RSHIFT 5 -> eb
+hx OR hy -> hz
+eu OR fa -> fb
+gj RSHIFT 3 -> gl
+fo AND fz -> gb
+1 AND jj -> jk
+jp OR ka -> kb
+de AND dk -> dm
+ex AND ez -> fa
+df OR dg -> dh
+iv OR jb -> jc
+x RSHIFT 5 -> aa
+NOT hj -> hk
+NOT im -> in
+fl LSHIFT 1 -> gf
+hu LSHIFT 15 -> hy
+iq OR ip -> ir
+iu RSHIFT 5 -> ix
+NOT fc -> fd
+NOT el -> em
+ck OR cl -> cm
+et RSHIFT 3 -> ev
+hw LSHIFT 1 -> iq
+ci RSHIFT 5 -> cl
+iv AND jb -> jd
+dd RSHIFT 5 -> dg
+as RSHIFT 2 -> at
+NOT jy -> jz
+af AND ah -> ai
+1 AND ds -> dt
+jx AND jz -> ka
+da LSHIFT 1 -> du
+fs AND fu -> fv
+jp RSHIFT 1 -> ki
+iw AND ix -> iz
+iw OR ix -> iy
+eo LSHIFT 15 -> es
+ev AND ew -> ey
+ba AND bc -> bd
+fp AND fv -> fx
+jc AND je -> jf
+et RSHIFT 2 -> eu
+kg OR kf -> kh
+iu OR jf -> jg
+er OR es -> et
+fo RSHIFT 2 -> fp
+NOT ca -> cb
+bv AND bx -> by
+u LSHIFT 1 -> ao
+cm AND co -> cp
+y OR ae -> af
+bn AND by -> ca
+1 AND ke -> kf
+jt AND jv -> jw
+fq OR fr -> fs
+dy AND ej -> el
+NOT kc -> kd
+ev OR ew -> ex
+dd OR do -> dp
+NOT cv -> cw
+gr AND gt -> gu
+dd RSHIFT 1 -> dw
+NOT gw -> gx
+NOT iz -> ja
+1 AND io -> ip
+NOT ag -> ah
+b RSHIFT 5 -> f
+NOT cr -> cs
+kb AND kd -> ke
+jr AND js -> ju
+cq AND cs -> ct
+il AND in -> io
+NOT ju -> jv
+du OR dt -> dv
+dd AND do -> dq
+b RSHIFT 2 -> d
+jm LSHIFT 1 -> kg
+NOT dq -> dr
+bo OR bu -> bv
+gk OR gq -> gr
+he OR hp -> hq
+NOT h -> i
+hf AND hl -> hn
+gv AND gx -> gy
+x AND ai -> ak
+bo AND bu -> bw
+hq AND hs -> ht
+hz RSHIFT 1 -> is
+gj RSHIFT 5 -> gm
+g AND i -> j
+gk AND gq -> gs
+dp AND dr -> ds
+b RSHIFT 3 -> e
+gl AND gm -> go
+gl OR gm -> gn
+y AND ae -> ag
+hv OR hu -> hw
+46065 -> b
+ab AND ad -> ae
+NOT ac -> ad
+1 AND ht -> hu
+NOT hn -> ho
A => day7/src/main.rs +196 -0
@@ 1,196 @@
+#[macro_use]
+extern crate lazy_static;
+use std::collections::HashMap;
+use regex::Regex;
+use std::io::BufRead;
+use std::ops::Deref;
+
+#[derive(Clone, Debug, PartialEq, Hash, Eq)]
+enum Wire {
+ Name(String),
+ Value(u16),
+}
+/// struct Wire(String);
+
+impl From<&str> for Wire {
+ fn from(s: &str) -> Wire {
+ match s.parse::<u16>() {
+ Ok(v) => Wire::Value(v),
+ Err(_) => Wire::Name(s.into()),
+ }
+ }
+}
+
+lazy_static! {
+ static ref LIT : Regex =
+ Regex::new(r"(\d+)").unwrap();
+ static ref LIT_WIRE : Regex =
+ Regex::new(r"([a-z]+)").unwrap();
+ static ref BIN_OP : Regex =
+ Regex::new(r"(.+) ([A-Z]+) (.+)").unwrap();
+ static ref NOT : Regex =
+ Regex::new(r"NOT ([a-z]+)").unwrap();
+ static ref INST : Regex =
+ Regex::new(r"(.+) -> (.+)").unwrap();
+}
+
+#[derive(Clone, Debug, PartialEq, Hash, Eq)]
+enum Expr {
+ Lit(u16),
+ Wire(Wire),
+ And(Wire, Wire),
+ Or(Wire, Wire),
+ LShift(Wire, u16),
+ RShift(Wire, u16),
+ Not(Wire),
+}
+
+impl From<&str> for Expr {
+ fn from(s: &str) -> Expr {
+ if let Some(c) = BIN_OP.captures(s) {
+ match &c[2] {
+ "AND" => {
+ return Expr::And(c[1].into(), c[3].into());
+ },
+ "OR" => {
+ return Expr::Or(c[1].into(), c[3].into());
+ },
+ "LSHIFT" => {
+ return Expr::LShift(c[1].into(), c[3].parse().unwrap());
+ },
+ "RSHIFT" => {
+ return Expr::RShift(c[1].into(), c[3].parse().unwrap());
+ },
+ s => {
+ dbg!(s);
+ unimplemented!()
+ }
+ }
+ }
+ if let Some(c) = NOT.captures(s) {
+ return Expr::Not(c[1].into());
+ }
+ if let Some(c) = LIT.captures(s) {
+ return Expr::Lit(c[1].parse().unwrap())
+ }
+ if let Some(c) = LIT_WIRE.captures(s) {
+ return Expr::Wire(c[1].into());
+ }
+ dbg!(s);
+ unimplemented!()
+ }
+}
+
+#[test]
+fn expr_from() {
+ assert_eq!(Expr::Lit(123), "123".into());
+ assert_eq!(Expr::And(Wire("ab".into()), Wire("b".into())), "ab AND b".into());
+ assert_eq!(Expr::Or(Wire("c".into()), Wire("d".into())), "c OR d".into());
+ assert_eq!(Expr::LShift(Wire("e".into()), 4), "e LSHIFT 4".into());
+ assert_eq!(Expr::RShift(Wire("f".into()), 8), "f RSHIFT 8".into());
+ assert_eq!(Expr::Not(Wire("g".into())), "NOT g".into());
+}
+
+#[derive(Clone, Debug, PartialEq, Hash, Eq)]
+struct Instruction {
+ expr: Expr,
+ dest: Wire,
+}
+
+impl From<&str> for Instruction {
+ fn from(s: &str) -> Instruction {
+ let cap = INST.captures(s).unwrap();
+ Instruction{expr: cap[1].into(), dest: cap[2].into()}
+ }
+}
+
+#[test]
+fn inst_from() {
+ assert_eq!(Instruction{expr: Expr::And(Wire("a".into()), Wire("b".into())), dest: Wire("c".into())},
+ "a AND b -> c".into());
+}
+
+#[derive(Clone, Debug, PartialEq, Hash, Eq)]
+enum Either {
+ Expr(Expr),
+ Value(u16),
+}
+
+fn eval(mut state: &mut HashMap<Wire, Either>, start: &Wire) -> u16 {
+ if let Wire::Value(n) = start {
+ return *n;
+ }
+ let value : Either = state.get(start).unwrap().clone();
+ match value {
+ Either::Value(n) => {
+ state.insert(start.clone(), Either::Value(n));
+ return n;
+ }
+ Either::Expr(e) => {
+ use Expr::*;
+ match e {
+ Lit(n) => {
+ state.insert(start.clone(), Either::Value(n));
+ return n;
+ }
+ Wire(w) => {
+ let val = eval(&mut state, &w);
+ state.insert(start.clone(), Either::Value(val));
+ return val;
+ }
+ And(l, r) => {
+ let lv = eval(&mut state, &l);
+ let rv = eval(&mut state, &r);
+ let val = lv & rv;
+ state.insert(start.clone(), Either::Value(val));
+ return val
+ }
+ Or(l, r) => {
+ let lv = eval(&mut state, &l);
+ let rv = eval(&mut state, &r);
+ let val = lv | rv;
+ state.insert(start.clone(), Either::Value(val));
+ return val
+ }
+ LShift(l, r) => {
+ let lv = eval(&mut state, &l);
+ let val = lv << r;
+ state.insert(start.clone(), Either::Value(val));
+ return val
+ }
+ RShift(l, r) => {
+ let lv = eval(&mut state, &l);
+ let val = lv >> r;
+ state.insert(start.clone(), Either::Value(val));
+ return val
+ }
+ Not(w) => {
+ let wv = eval(&mut state, &w);
+ let val = !wv;
+ state.insert(start.clone(), Either::Value(val));
+ return val
+ }
+ _ => unimplemented!()
+ }
+ },
+ };
+ println!("{:?}", state);
+ unimplemented!()
+}
+
+fn main() {
+ let all : Vec<Instruction> = std::io::BufReader::new(std::io::stdin())
+ .lines()
+ .map(|s| s.unwrap())
+ .map(|s| s.deref().into())
+ .collect();
+ let mut map = HashMap::new();
+ for inst in all {
+ map.insert(inst.dest, Either::Expr(inst.expr));
+ }
+ let mut state = map.clone();
+ let aval = dbg!(eval(&mut state, &Wire::Name("a".into())));
+ map.insert(Wire::Name("b".into()), Either::Value(aval));
+ let mut state = map.clone();
+ let aval = dbg!(eval(&mut state, &Wire::Name("a".into())));
+}
A => day_4/Cargo.toml +7 -0
@@ 1,7 @@
+[package]
+name = "day_4"
+version = "0.1.0"
+authors = ["Tomasz Kłak <tomasz@tomaszklak.pl>"]
+
+[dependencies]
+md5 = "0.3.6"
A => day_4/src/main.rs +17 -0
@@ 1,17 @@
+extern crate md5;
+
+fn solve(prefix: &str, dificulty: &str) -> i32 {
+ for i in 1.. {
+ let candidate = format!("{}{}", prefix, i);
+ let dig = md5::compute(candidate);
+ if format!("{:x}", dig).starts_with(dificulty) {
+ return i
+ }
+ }
+ unreachable!();
+}
+
+fn main() {
+ println!("{}", solve("bgvyzdsv", "00000"));
+ println!("{}", solve("bgvyzdsv", "000000"));
+}