Advertisement
Guest User

AoC day 4, Smalltalk

a guest
Dec 4th, 2020
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. "*
  4.  *   A subclass of IdentityDictionary that can store and validate passport fields
  5.  *"
  6. IdentityDictionary subclass: Passport [
  7.     <shape: #pointer>
  8.  
  9.     " Initializer for the Passport Validator class variable "
  10.     Passport class >> initialize [
  11.         Validator := IdentityDictionary new.
  12.         Validator at: #byr put: [:v | v asInteger between: 1920 and: 2002 ];
  13.                   at: #iyr put: [:v | v asInteger between: 2010 and: 2020 ];
  14.                   at: #eyr put: [:v | v asInteger between: 2020 and: 2030 ];
  15.  
  16.                   at: #hcl put: [:v | (v =~ '^#[[:xdigit:]]{6}$') matched ];
  17.                   at: #ecl put: [:v | (v =~ '^(amb|blu|brn|gry|grn|hzl|oth)$') matched ];
  18.                   at: #pid put: [:v | (v =~ '^[[:digit:]]{9}$') matched ];
  19.  
  20.                   at: #hgt put: [ :v |
  21.                                    (v =~ '^([[:digit:]]+)(cm|in)$') ifMatched: [ :res |
  22.                                       | h |
  23.                                        h := (res at: 1) asInteger.
  24.                                        ((res at: 2) = 'cm') ifTrue: [
  25.                                            h between: 150 and: 193
  26.                                        ] ifFalse: [
  27.                                            h between: 59 and: 76
  28.                                        ]
  29.                                    ] ifNotMatched: [
  30.                                        false
  31.                                    ]
  32.                                ];
  33.                  at: #cid put: [:v | true ].
  34.     ]
  35.  
  36.     " Check if all the needed fields are in this ID "
  37.     hasAllFields [
  38.         #(#byr #iyr #eyr #hcl #ecl #pid #hgt) do: [ :key |
  39.             self at: key ifAbsent: [
  40.                 ^false
  41.             ]
  42.         ].
  43.         ^true
  44.     ]
  45.  
  46.     " Check if all the fields we have in this ID are valid "
  47.     fieldsValid [
  48.         (Validator isNil) ifTrue: [ Passport initialize ].
  49.  
  50.         (self keys) do: [ :key |
  51.             ((Validator at: key) value: (self at: key)) ifFalse: [
  52.                 ^false
  53.             ]
  54.         ].
  55.  
  56.         ^true
  57.     ]
  58. ]
  59.  
  60. "*
  61.  *   A class for parsing stdin, returning Passports (nil if done)
  62.  *"
  63. Object subclass: IDParser [
  64.     | inStream |
  65.  
  66.     IDParser class >> new [
  67.         ^(super new) init
  68.     ]
  69.  
  70.     init [
  71.         "*
  72.          *  stdin has a bug in Gnu Smalltalk where it resets back to the beginning,
  73.          *  so I'm just snarfing all the contents and putting my own ReadStream on that.
  74.          *"
  75.         inStream := stdin lines contents readStream.
  76.         ^self
  77.     ]
  78.  
  79.     " parse lines until we have a full Passport, then return it (nil if done) "
  80.     nextPassport [
  81.         | line id key_value |
  82.  
  83.         id := Passport new.
  84.  
  85.         [ (line := inStream next) notNil and: [(line =~ '^$') matched not] ] whileTrue: [
  86.             (line subStrings: ' ') do: [ :field |
  87.                 key_value := (field subStrings: ':').
  88.                 id at: (key_value at: 1) asSymbol put: (key_value at: 2).
  89.             ]
  90.         ].
  91.  
  92.         (id size == 0) ifTrue: [ ^nil ].  " Should only happen at end "
  93.  
  94.         ^id
  95.     ]
  96. ]
  97.  
  98. "*
  99.  *   Mainline
  100.  *"
  101. part1 := 0.
  102. part2 := 0.
  103.  
  104. parse := IDParser new.
  105.  
  106. [ (id := parse nextPassport) notNil ] whileTrue: [
  107.     (id hasAllFields) ifTrue: [
  108.         part1 := part1 + 1.
  109.  
  110.         (id fieldsValid) ifTrue: [
  111.             part2 := part2 + 1
  112.         ]
  113.     ]
  114. ].
  115.  
  116. stdout nextPutAll: 'Part 1: ', part1 asString; nl.
  117. stdout nextPutAll: 'Part 2: ', part2 asString; nl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement