Background
K functions have a feature called projection, which is essentially partial application of values to a function. The syntax for projections is a natural extension of the regular function call syntax:
f[1;2;3] / call a ternary function f with three arguments 1, 2, 3
f[1;2;] / the third argument is missing,
/ so it evaluates to a unary derived function instead
f[1;2;][3] / calling the derived function with 3 calls f with 1, 2, 3
/ so this is equivalent to calling f[1;2;3]
Projections can supply any number of arguments and missing slots, and omit trailing semicolons. The function is evaluated only when all missing slots are filled and the number of arguments is at least the function's arity. For the sake of this challenge, let's assume the arity of f
is infinity, i.e. it is never actually evaluated.
The right side shows how ngn/k prettyprints projections. You can freely experiment with ngn/k online interpreter.
f[1] / -> f[1]
f[1;2] / -> f[1;2]
f[;2] / -> f[;2]
f[;2][1] / -> f[1;2]
A projection also decides the minimum number of arguments f
will be actually called with. For example, f[1;]
specifies that the first arg is 1
and the second arg will come later. It is different from f[1]
, and the two are formatted differently.
f[1] / -> f[1]
f[1;] / -> f[1;]
You can create projections out of projections too, which is the main subject of this challenge. Given an existing projection P
and the next projection Q
, the following happens:
- For each existing empty slot in
P
, each (filled or empty) slot inQ
is sequentially matched from left to right, replacing the corresponding empty slot inP
. - If
Q
is exhausted first, the remaining slots inP
are untouched. - If
P
is exhausted first, the remaining slots inQ
are added to the end.
f[;;1;;] / a projection with five slots, 3rd one filled with 1
f[;;1;;][2] / -> f[2;;1;;]
/ 2 fills the first empty slot
f[;;1;;][2;3;4] / -> f[2;3;1;4;]
/ 2, 3, 4 fills the first three empty slots
/ (1st, 2nd, 4th argument slot respectively)
f[;;1;;][2;;4] / -> f[2;;1;4;]
/ the second empty slot (2nd arg slot) remains empty
f[;;1;;][2;;4;;6] / -> f[2;;1;4;;6]
/ Q specifies five slots, but P has only four empty slots
/ so the 6 is added as an additional (6th overall) slot
Challenge
Given a series of projections applied to f
, simplify it to a single projection as described above.
The input is given as a string which represents the function f
followed by one or more projections, where each projection specifies one or more (filled or empty) slots. You may further assume that
- the substring
[]
does not appear in the input (it means something slightly different), - each filled slot (specified argument) contains a single integer between 1 and 9 inclusive, and
- the entire input does not have any spaces.
Standard code-golf rules apply. The shortest code in bytes wins.
Test cases
All the examples are replicated here, and a "stress test" is presented at the bottom.
Basic tests
f[1] -> f[1]
f[1;] -> f[1;]
f[1;2] -> f[1;2]
f[;2] -> f[;2]
f[;2][1] -> f[1;2]
f[1;2;3] -> f[1;2;3]
f[1;2;] -> f[1;2;]
f[1;2;][3] -> f[1;2;3]
f[;;1;;] -> f[;;1;;]
f[;;1;;][2] -> f[2;;1;;]
f[;;1;;][2;3;4] -> f[2;3;1;4;]
f[;;1;;][2;;4] -> f[2;;1;4;]
f[;;1;;][2;;4;;6] -> f[2;;1;4;;6]
Stress tests (input)
f[;1]
f[;1][;2]
f[;1][;2][3]
f[;1][;2][3][;;;4]
f[;1][;2][3][;;;4][;5]
f[;1][;2][3][;;;4][;5][6;]
f[;1][;2][3][;;;4][;5][6;][7]
f[;1][;2][3][;;;4][;5][6;][7;;]
f[1;;;;;;;;;;;;;]
f[1;;;;;;;;;;;;;][2][3]
f[1;;;;;;;;;;;;;][2][3][;;;;;4;;;;;;;;]
f[1;;;;;;;;;;;;;][2][3][;;;;;4;;;;;;;;][5;6;7;8;9;1][2;3;4;5][6;7]
Stress tests (output)
f[;1]
f[;1;2]
f[3;1;2]
f[3;1;2;;;;4]
f[3;1;2;;5;;4]
f[3;1;2;6;5;;4]
f[3;1;2;6;5;7;4]
f[3;1;2;6;5;7;4;;]
f[1;;;;;;;;;;;;;]
f[1;2;3;;;;;;;;;;;]
f[1;2;3;;;;;;4;;;;;;;;]
f[1;2;3;5;6;7;8;9;4;1;2;3;4;5;6;7;]
f[1;]
andf[1]
should be considered different. \$\endgroup\$f[1;]
andf[1]
(f
having arity>1) are technically different, when all slots get filled it won't matter whether you started withf[1;]
orf[1]
\$\endgroup\$