Skip to content

Instantly share code, notes, and snippets.

@seoh
Created April 11, 2021 10:52
Show Gist options
  • Save seoh/657da40777f16331b4eaab28fd38772e to your computer and use it in GitHub Desktop.
Save seoh/657da40777f16331b4eaab28fd38772e to your computer and use it in GitHub Desktop.
advent of code 2020, day 4 solution using rescript. help me
type passport = {
byr: option<int>,
iyr: option<int>,
eyr: option<int>,
hgt: option<(int, string)>,
hcl: option<string>,
ecl: option<string>,
pid: option<string>,
// cid: option<string>,
}
let empty: (_ => passport) = _ => ({
byr: None, iyr: None, eyr: None, hgt: None,
hcl: None, ecl: None, pid: None
})
let split = string =>
string
-> Js.String2.split("\n")
-> Array.reduce(
list{ list{} },
(acc, line) => if Js.String.length(line) > 0 {
switch acc {
| list{ h, ...tail } => List.add(tail, List.add(h, line))
| _ => Js.log(acc); acc
}
} else { List.add(acc, list{}) },
)
let validKeys = ["byr", "iyr", "eyr", "hgt", "hcl", "ecl", "pid"]
let validate1 = (dicts: Js.Dict.t<string>) => {
let keys = Set.String.fromArray(Js.Dict.keys(dicts))
let valid = Set.String.fromArray(validKeys)
Set.String.subset(keys, valid) &&
(Set.String.size(keys) == Set.String.size(valid) || // has full keys or
(Set.String.size(keys) == Set.String.size(valid) - 1 && // except only cid
!Set.String.has(keys, "cid")))
}
let validate2 = dicts => {
let pass = Array.reduce(
Js.Dict.entries(dicts),
empty(),
(obj, (k, v)) => {
switch k {
| "byr" =>
let value = Option.flatMap(Int.fromString(v), yr =>
if 1920 <= yr && yr <= 2002 { Some(yr) }
else { None })
{ ...obj, byr: value }
| "iyr" =>
let value = Option.flatMap(Int.fromString(v), yr =>
if 2010 <= yr && yr <= 2020 { Some(yr) }
else { None })
{ ...obj, iyr: value }
| "eyr" =>
let value = Option.flatMap(Int.fromString(v), yr =>
if 2020 <= yr && yr <= 2030 { Some(yr) }
else { None })
{ ...obj, eyr: value }
| "hgt" =>
let value = switch Js.String2.match_(v, %re("/(\d+)(\w{2})/")) {
| Some([_, number, unit]) =>
Option.flatMap(Int.fromString(number), n =>
switch unit {
| "cm" =>
if 150 <= n && n <= 193 { Some((n, unit)) }
else { None }
| "in" =>
if 59 <= n && n <= 76 { Some((n, unit)) }
else { None }
| _ => None
})
| a => Js.log((v, a)); None
}
{ ...obj, hgt: value }
| "hcl" =>
switch Js.String2.match_(v, %re("/#[0-9a-f]{6}/") ) {
| Some(_) => { ...obj, hcl: Some(v) }
| _ => obj
}
| "ecl" =>
let eyes = ["amb", "blu", "brn", "gry", "grn", "hzl", "oth"]
if Js.Array.includes(v, eyes) { {...obj, ecl: Some(v)} }
else { obj }
| "pid" =>
switch Js.String2.match_(v, %re("/[0-9]{9}/") ) {
| Some(_) => {...obj, pid: Some(v)}
| _ => obj
}
| _ => obj
}
}
)
Js.log(pass)
Option.isSome(pass.byr) &&
Option.isSome(pass.iyr) &&
Option.isSome(pass.eyr) &&
Option.isSome(pass.hgt) &&
Option.isSome(pass.hcl) &&
Option.isSome(pass.ecl) &&
Option.isSome(pass.pid)
}
let refine = (input: list<list<string>>) =>
input
-> List.map(lines => {
lines
-> List.map(line =>
line
-> Js.String2.split(" ")
-> List.fromArray
)
-> List.flatten
-> List.keepMap(kv => {
switch(Js.String.split(":", kv)) {
| [k, v] => Some((k, v))
| _ => None
}
})
-> Js.Dict.fromList
})
// -> List.keep(validate1)
-> List.keep(validate2)
Node.Fs.readFileAsUtf8Sync("input/day4.txt")
-> split
-> refine
-> List.length
-> Js.log
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment