Author: Nicholas Prado <nmprado@nzen.ws>
Date: Sat Dec 5 23:13:02 UTC 2020
Parent: 55c763b6ba38065a1a111e6a9370a9f2a476488e
Log message:
feat 200402 validates passports
This only needed one regex, thankfully.
1: diff --git a/src/java/Exercise200402.java b/src/java/Exercise200402.java
2: new file mode 100644
3: index 0000000..55a3e1c
4: --- /dev/null
5: +++ b/src/java/Exercise200402.java
6: @@ -0,0 +1,273 @@
7: +
8: +import java.io.IOException;
9: +import java.nio.file.Files;
10: +import java.nio.file.InvalidPathException;
11: +import java.nio.file.Path;
12: +import java.nio.file.Paths;
13: +import java.util.Collection;
14: +import java.util.HashSet;
15: +import java.util.LinkedList;
16: +import java.util.List;
17: +import java.util.Map;
18: +import java.util.regex.*;
19: +import java.util.Set;
20: +import java.util.TreeMap;
21: +
22: +public class Exercise200402
23: +{
24: +
25: + public static void main( String args[] )
26: + {
27: + final String here = "e20042.m ";
28: + if ( args.length < 1 )
29: + {
30: + throw new RuntimeException( here +"add a filename argument" );
31: + }
32: + String userSaysFile = args[ 0 ];
33: + List<String> fileLines = new LinkedList<>();
34: + try
35: + {
36: + Path where = Paths.get( userSaysFile );
37: + fileLines = Files.readAllLines( where );
38: + }
39: + catch ( IOException | InvalidPathException ie )
40: + {
41: + System.err.println( here +"couldn't read file "+ userSaysFile +" because "+ ie );
42: + return;
43: + }
44: + /*
45: + - interpretation of spec -
46: + */
47: + int valid = 0;
48: + Collection<String> onePassport = new LinkedList<>();
49: + int lineNum = 0;
50: + boolean parsing = false;
51: + Exercise200402 buh = new Exercise200402();
52: + Pattern hexColor = Pattern.compile( "#[abcdef\\d]{6}" );
53: + for ( String line : fileLines )
54: + {
55: + if ( line.isEmpty() )
56: + {
57: + lineNum += 1;
58: + if ( ! onePassport.isEmpty() )
59: + {
60: + Exercise200402.Passport person = buh.new Passport( onePassport );
61: + if ( person.valid( hexColor ) )
62: + {
63: + valid += 1;
64: + System.out.println( "\t"+ person );
65: + }
66: + }
67: + onePassport.clear();
68: + continue;
69: + }
70: + else
71: + {
72: + onePassport.add( line );
73: + }
74: + }
75: + if ( ! onePassport.isEmpty() )
76: + {
77: + Exercise200402.Passport person = buh.new Passport( onePassport );
78: + if ( person.valid( hexColor ) )
79: + {
80: + valid += 1;
81: + System.out.println( "\t"+ person );
82: + }
83: + }
84: + System.out.println( here +"input summed to "+ valid +" of "+ lineNum +" total" );
85: + }
86: +
87: +
88: + private class Passport
89: + {
90: + String birthYear = "";
91: + String issueYear = "";
92: + String expirationYear = "";
93: + String height = "";
94: + String hairColor = "";
95: + String eyeColor = "";
96: + String passportId = "";
97: + String countryId = "";
98: + final String byr = "byr",
99: + iyr = "iyr",
100: + eyr = "eyr",
101: + hgt = "hgt",
102: + hcl = "hcl",
103: + ecl = "ecl",
104: + pid = "pid",
105: + cid = "cid";
106: +
107: + public Passport(
108: + Collection<String> input
109: + ) {
110: + parse( input );
111: + }
112: + private void parse(
113: + Collection<String> input
114: + ) {
115: + final String here = "e20012.pp.p ";
116: + for ( String line : input )
117: + {
118: + String[] lineElements = line.split( " " );
119: + for ( String element : lineElements )
120: + {
121: + int colonInd = element.indexOf( ':' );
122: + String aspect = element.substring( 0, colonInd );
123: + String content = element.substring( colonInd +1 );
124: + switch ( aspect )
125: + {
126: + case byr :
127: + birthYear = content;
128: + break;
129: + case iyr :
130: + issueYear = content;
131: + break;
132: + case eyr :
133: + expirationYear = content;
134: + break;
135: + case hgt :
136: + height = content;
137: + break;
138: + case hcl :
139: + hairColor = content;
140: + break;
141: + case ecl :
142: + eyeColor = content;
143: + break;
144: + case pid :
145: + passportId = content;
146: + break;
147: + case cid :
148: + countryId = content;
149: + break;
150: + }
151: + }
152: + }
153: + }
154: + public boolean valid(
155: + Pattern hexColor
156: + ) {
157: + if ( birthYear.isEmpty()
158: + || issueYear.isEmpty()
159: + || expirationYear.isEmpty()
160: + || height.isEmpty()
161: + || hairColor.isEmpty()
162: + || eyeColor.isEmpty()
163: + || passportId.isEmpty() )
164: + // || countryId.isEmpty(); // haha, hacking
165: + {
166: + // System.out.println( "v not full" );
167: + return false;
168: + }
169: + else if ( ! clamp( birthYear, 1920, 2002 ) )
170: + {
171: + // System.out.println( "v not birthyear "+ birthYear );
172: + return false;
173: + }
174: + else if ( ! clamp( issueYear, 2010, 2020 ) )
175: + {
176: + // System.out.println( "v not issueYear "+ issueYear );
177: + return false;
178: + }
179: + else if ( ! clamp( expirationYear, 2020, 2030 ) )
180: + {
181: + // System.out.println( "v not expirationYear "+ expirationYear );
182: + return false;
183: + }
184: + else if ( ! eye() )
185: + {
186: + // System.out.println( "v not eye "+ eyeColor );
187: + return false;
188: + }
189: + else if ( ! height() )
190: + {
191: + // System.out.println( "v not eye "+ eyeColor );
192: + return false;
193: + }
194: + else if ( ! hexColor.matcher( hairColor ).find() )
195: + {
196: + // System.out.println( "v not hair matcher "+ hairColor );
197: + return false;
198: + }
199: + else if ( passportId.length() != 9 || ! clamp( passportId, 0, 999_999_999 ) )
200: + {
201: + // System.out.println( "v not passport "+ passportId );
202: + return false;
203: + }
204: + return true;
205: + }
206: + private boolean clamp(
207: + String asChars, int min, int max
208: + ) {
209: + try {
210: + int value = Integer.parseInt( asChars );
211: + return value >= min && value <= max;
212: + }
213: + catch ( NumberFormatException nfe )
214: + {
215: + return false;
216: + }
217: + }
218: + private boolean eye(
219: + ) {
220: + return eyeColor.equals( "amb" )
221: + || eyeColor.equals( "blu" )
222: + || eyeColor.equals( "brn" )
223: + || eyeColor.equals( "gry" )
224: + || eyeColor.equals( "grn" )
225: + || eyeColor.equals( "hzl" )
226: + || eyeColor.equals( "oth" );
227: + }
228: + private boolean height(
229: + ) {
230: + if ( height.endsWith( "in" ) )
231: + return clamp( height.substring( 0, height.length() -2 ), 59, 76 );
232: + else if ( height.endsWith( "cm" ) )
233: + return clamp( height.substring( 0, height.length() -2 ), 150, 193 );
234: + else
235: + return false;
236: + }
237: + public String toString(
238: + ) {
239: + return ""/*
240: + "by"+ birthYear
241: + +" iy"+ issueYear
242: + +"\t ey"+ expirationYear
243: + +"\t ec_"+ eyeColor
244: + */
245: + +"\t h "+ height.substring( 0, height.length() -2 ) +"_"+ height.substring( height.length() -2 )
246: + /*
247: + +" pi"+ passportId
248: + +" _"+ hairColor
249: + */ ;
250: + }
251: + }
252: +}
253: +
254: +
255: +
256: +
257: +
258: +
259: +
260: +
261: +
262: +
263: +
264: +
265: +
266: +
267: +
268: +
269: +
270: +
271: +
272: +
273: +
274: +
275: +
276: +
277: +
278: +
279: +
280: diff --git a/src/res/20_04_2_example.txt b/src/res/20_04_2_example.txt
281: new file mode 100644
282: index 0000000..b526855
283: --- /dev/null
284: +++ b/src/res/20_04_2_example.txt
285: @@ -0,0 +1,26 @@
286: +eyr:1972 cid:100
287: +hcl:#18171d ecl:amb hgt:170 pid:186cm iyr:2018 byr:1926
288: +
289: +iyr:2019
290: +hcl:#602927 eyr:1967 hgt:170cm
291: +ecl:grn pid:012533040 byr:1946
292: +
293: +hcl:dab227 iyr:2012
294: +ecl:brn hgt:182cm pid:021572410 eyr:2020 byr:1992 cid:277
295: +
296: +hgt:59cm ecl:zzz
297: +eyr:2038 hcl:74454a iyr:2023
298: +pid:3556412378 byr:2007
299: +
300: +pid:087499704 hgt:74in ecl:grn iyr:2012 eyr:2030 byr:1980
301: +hcl:#623a2f
302: +
303: +eyr:2029 ecl:blu cid:129 byr:1989
304: +iyr:2014 pid:896056539 hcl:#a97842 hgt:165cm
305: +
306: +hcl:#888785
307: +hgt:164cm byr:2001 iyr:2015 cid:88
308: +pid:545766238 ecl:hzl
309: +eyr:2022
310: +
311: +iyr:2010 hgt:158cm hcl:#b6652a ecl:blu byr:1944 eyr:2021 pid:093154719
312: \ No newline at end of file