aboutsummaryrefslogtreecommitdiff
path: root/challenge-100/paulo-custodio/forth/ch-1.fs
blob: 8256d36e219a42901aed2f600704d9e2447e11f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#! /usr/bin/env gforth

\ Challenge 100
\
\ TASK #1 > Fun Time
\ Submitted by: Mohammad S Anwar
\ You are given a time (12 hour / 24 hour).
\
\ Write a script to convert the given time from 12 hour format to 24 hour format and vice versa.
\
\ Ideally we expect a one-liner.
\
\ Example 1:
\ Input: 05:15 pm or 05:15pm
\ Output: 17:15
\ Example 2:
\ Input: 19:15
\ Output: 07:15 pm or 07:15pm

\ skip blanks
: skip-blanks       ( str len -- str len )
    BEGIN
        DUP 0= IF EXIT THEN                             \ string empty
        OVER C@ BL <> IF EXIT THEN                      \ not space
        1 /STRING
    AGAIN
;

\ parse a time string, return number of minutes since midnight
\ and true if it was in AM/PM format
: parse-time        { str len -- hours minutes f-am-pm }
    0 0 { hours minutes }
    0 0 str len >NUMBER TO len TO str DROP TO hours     \ convert hours
    str C@ ':' <> IF 1 THROW THEN
    str len 1 /STRING TO len TO str                     \ skip ':'
    0 0 str len >NUMBER TO len TO str DROP TO minutes   \ convert minutes
    str len skip-blanks TO len TO str                   \ spaces
    len 0= IF
        hours minutes FALSE
    ELSE str C@ DUP 'a' = SWAP 'A' = OR IF              \ AM
        hours 12 = IF 0 TO hours THEN
        hours minutes TRUE
    ELSE str C@ DUP 'p' = SWAP 'P' = OR IF              \ PM
        hours 12 <> IF hours 12 + TO hours THEN
        hours minutes TRUE
    THEN THEN THEN
;

\ output in 24-hour format
: print24       ( hours minutes -- )
    SWAP 100 * + 0                  \ convert to hhmm in decimal, double
    <# # # ':' HOLD # # #> TYPE
;

\ output in 12-hour format
: print12       { hours minutes -- }
    FALSE { pm }                    \ assume AM

    hours DUP 12 > IF
        DROP hours 12 - TO hours TRUE TO pm ELSE
    DUP 12 = IF
        DROP TRUE TO pm ELSE
    DUP 0= IF
        DROP 12 TO HOURS
    ELSE DROP THEN THEN THEN

    hours minutes print24
    pm IF ." pm" ELSE ." am" THEN
;

\ convert time
: convert-time      ( str len -- )
    parse-time IF print24 ELSE print12 THEN
;

\ main
NEXT-ARG convert-time CR BYE