aboutsummaryrefslogtreecommitdiff
path: root/challenge-204/paulo-custodio/forth/ch-2.fs
blob: 08442d965eda6f11ecfd017b74c1f2ad4275dbff (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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#! /usr/bin/env gforth

\ Challenge 204
\
\ Task 2: Reshape Matrix
\ Submitted by: Mohammad S Anwar
\
\ You are given a matrix (m x n) and two integers (r) and (c).
\
\ Write a script to reshape the given matrix in form (r x c) with the original value in the given matrix. If you can’t reshape print 0.
\
\ Example 1
\
\ Input: [ 1 2 ]
\        [ 3 4 ]
\
\        $matrix = [ [ 1, 2 ], [ 3, 4 ] ]
\        $r = 1
\        $c = 4
\
\ Output: [ 1 2 3 4 ]
\
\ Example 2
\
\ Input: [ 1 2 3 ]
\        [ 4 5 6 ]
\
\        $matrix = [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
\        $r = 3
\        $c = 2
\
\ Output: [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]
\
\         [ 1 2 ]
\         [ 3 4 ]
\         [ 5 6 ]
\
\ Example 3
\
\ Input: [ 1 2 ]
\
\        $matrix = [ [ 1, 2 ] ]
\        $r = 3
\        $c = 2
\
\ Output: 0

\ array of numbers, setup by collect-args
CREATE items 256 CELLS ALLOT
0 VALUE num_items                   \ number of elements

: items[] ( i -- addr )
    CELLS items +
;

: push_item ( n -- )
    num_items items[] !
    num_items 1+ TO num_items
;

0 VALUE out_rows
0 VALUE out_cols

\ scanner
1024 CONSTANT max_line
CREATE line  max_line ALLOT
line VALUE line_ptr
0 VALUE line_len
9 CONSTANT TAB
0 CONSTANT EOL

\ read next line, return false on eof
: read_line ( -- ok )
    line TO line_ptr
    line max_line stdin READ-LINE THROW     ( len flag )
    SWAP
    DUP TO line_len
    line + EOL SWAP C!                      \ store end marker
;

\ get current char, 0 at end of line
: cur_char ( -- ch )
    line_ptr C@
;

\ next non-blank char, 0 at end of line
: next_char ( -- ch )
    0 { ch }
    BEGIN
        cur_char TO ch
        ch EOL = IF EXIT THEN
        ch BL =  ch TAB =  OR
    WHILE
        line_ptr 1+ TO line_ptr
    REPEAT
    ch
;

: parse_char { ch -- ok }
    next_char ch = IF
        line_ptr 1+ TO line_ptr
        TRUE
    ELSE
        FALSE
    THEN
;

: parse_number ( -- n true | 0 false )
    next_char DUP '0' >= SWAP '9' <= AND IF
        0 0 line_ptr  line_len  line_ptr line - -   ( 0. addr len )
        >NUMBER DROP TO line_ptr
        DROP TRUE
    ELSE
        0 0
    THEN
;


\ parse input
: parse_matrix_line ( -- ok )
    '[' parse_char IF
        BEGIN parse_number WHILE
            push_item
        REPEAT
        DROP
        ']' parse_char DROP
        TRUE
    ELSE
        FALSE
    THEN
;

: parse_matrix ( -- )
    BEGIN read_line WHILE
        parse_matrix_line 0= IF EXIT THEN
    REPEAT
;

: parse_input ( -- )
    parse_matrix
    parse_number DROP TO out_rows
    parse_number DROP TO out_cols
;


\ print output
: output_matrix ( -- )
    out_rows out_cols *  num_items = IF
        out_rows 0 DO
            '[' EMIT
            out_cols 0 DO
                J out_cols * I + items[] @ .
            LOOP
            ']' EMIT CR
        LOOP
    ELSE
        0 . CR
    THEN
;


parse_input output_matrix
BYE