diff options
| author | Archargelod <archargelod@gmail.com> | 2024-03-08 19:02:07 +0800 |
|---|---|---|
| committer | Archargelod <archargelod@gmail.com> | 2024-03-08 19:02:07 +0800 |
| commit | c45f2d8a7ae3836921747c832d2bfe9db7cc9aa9 (patch) | |
| tree | cea6fb0f51440f00210ab68d018e334c92bc7ef5 /challenge-259 | |
| parent | 510484bb98b0d2413f8c09c0a827e91b992d2533 (diff) | |
| download | perlweeklychallenge-club-c45f2d8a7ae3836921747c832d2bfe9db7cc9aa9.tar.gz perlweeklychallenge-club-c45f2d8a7ae3836921747c832d2bfe9db7cc9aa9.tar.bz2 perlweeklychallenge-club-c45f2d8a7ae3836921747c832d2bfe9db7cc9aa9.zip | |
weeks 27-40, 259 in Nim
Diffstat (limited to 'challenge-259')
| -rwxr-xr-x | challenge-259/archargelod/nim/ch_1.nim | 32 | ||||
| -rwxr-xr-x | challenge-259/archargelod/nim/ch_2.nim | 96 |
2 files changed, 128 insertions, 0 deletions
diff --git a/challenge-259/archargelod/nim/ch_1.nim b/challenge-259/archargelod/nim/ch_1.nim new file mode 100755 index 0000000000..9f058082b6 --- /dev/null +++ b/challenge-259/archargelod/nim/ch_1.nim @@ -0,0 +1,32 @@ +#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off +import std/times + +proc bankingDay( + date: DateTime, offset: int, holidays: openarray[DateTime] = @[] +): DateTime = + result = date + + var offset = offset + while offset > 0: + result += 1.days + if result.weekday notin {dSat, dSun} and result notin holidays: + dec offset + +when isMainModule: + import std/unittest + + let + Test: seq[tuple[start: DateTime, offset: int, holidays: seq[DateTime]]] = @[ + (dateTime(2018, mJun, 28), 3, @[dateTime(2018, mJul, 3)]), + (dateTime(2018, mJun, 28), 3, @[]), + ] + Expected = [ + dateTime(2018, mJul, 4), + dateTime(2018, mJul, 3), + ] + + suite "Banking Day Offset": + test "Example 1": + check bankingDay(Test[0].start, Test[0].offset, Test[0].holidays) == Expected[0] + test "Example 2": + check bankingDay(Test[1].start, Test[1].offset, Test[1].holidays) == Expected[1] diff --git a/challenge-259/archargelod/nim/ch_2.nim b/challenge-259/archargelod/nim/ch_2.nim new file mode 100755 index 0000000000..0928ec77c3 --- /dev/null +++ b/challenge-259/archargelod/nim/ch_2.nim @@ -0,0 +1,96 @@ +#!/usr/bin/env -S nim r -d:release --verbosity:0 --hints:off +import std/[strutils, parseutils, tables] + +type + ValueKind = enum + StringValue + IntValue + + Value = object + case kind: ValueKind + of StringValue: + strval: string + of IntValue: + intval: int + + Struct = object + id: string + fields: OrderedTable[string, Value] # assuming order is important + +proc `==`(v: Value, s: string): bool = + v.kind == StringValue and v.strval == s + +proc `==`(v: Value, i: SomeInteger): bool = + v.kind == IntValue and v.intval == i + +template consume(input: string, amount: int = 1) = + index += amount + if index > input.high: + raise newException(ValueError, "Unexpected end.") + +template consume(input, token: string) = + for i, c in token: + if index + i > input.high or c != input[index + i]: + raise newException(ValueError, "Expected: " & token) + index += token.len + +proc parseStruct(input: string): Struct = + var index = 0 + input.consume("{%") + + # parse ID + index += input.skipWhitespace(index) + let tokenLength = input.skipWhile(Letters + Digits + {'_'}, index) + result.id = input[index ..< index + tokenLength] + index += tokenLength + + index += input.skipWhitespace(index) + + # parse fields + while index < input.len: + if input[index] notin Letters + Digits + {'_'}: + break + + let fieldNameLength = input.skipWhile(Letters + Digits + {'_'}, index) + if index + fieldNameLength > input.high: + raise newException(ValueError, "Unexpected end.") + + let fieldName = input[index ..< index + fieldNameLength] + input.consume fieldNameLength + + input.consume "=" + + if input[index] == '"': + input.consume() + var strVal = "" + while true: + if input[index] == '\\': + input.consume() + elif input[index] == '"': + break + strVal &= input[index] + input.consume() + + result.fields[fieldName] = Value(kind: StringValue, strval: strVal) + input.consume "\"" + else: + let intLength = input.skipWhile(Digits, index) + let intVal = parseInt(input[index ..< index + intLength]) + result.fields[fieldName] = Value(kind: IntValue, intval: intVal) + input.consume intLength + + input.consume input.skipWhitespace(index) + input.consume "%}" + +when isMainModule: + import std/unittest + + const + Test = """{% youtube title="Title \\ \"quoted\" done" some_field=12 %}""" + + suite "Line Parser": + test "Example 1": + let struct = parseStruct(Test) + check struct.id == "youtube" + check struct.fields["title"] == "Title \\ \"quoted\" done" + check struct.fields["some_field"] == 12 |
