n=e=$Input;
a=0;
w=While[{m=Modulo[$e];Not[m[1]];}];
w=w[{f=For[4];f=f[@x];f=f[{Print[$e];q=Equal[$x];i=If[{q[1];}];i=i[{k=Times[$e];}];Do[$i];i=If[{q[2];}];i=i[{k=Add[$e];}];Do[$i];i=If[{q[3];}];i=i[{k=Subtract[$e];}];Do[$i];i=If[{q[4];}];i=i[{k=Divide[$e];}];Do[$i];e=k[a=Increment[$a]];}];Do[$f];}];
Do[$w];
Try it online!
It's about time I used Rutger again. Unfortunately, it may not be the best language for the task, as it has no form of eval
, forcing me to use four if statements
How it works
How Rutger works
A brief foreword on how the language works: Everything is either an assignment or a function, and every function takes exactly one argument. For operations that require more than one argument (e.g. multiplication), the first call returns a partial function, that, when called again with the second argument, returns the expected result. For example:
left = Times[5];
Print[left[6]];
will print out 30: Try it online!. While usually this is longer than the usual alternative, it can at times save bytes, if a function is called repeatedly with one constant argument, and one changing argument, for instance when printing out times tables.
This one argument rule applies to everything that isn't a constant or a variable, including loops and conditionals. However, loops and conditionals (For
, Each
, While
, DoWhile
, If
and IfElse
) are doable, meaning that in order to actually run them, the Do
function must be called (see the last line in the answer). Again, this can save bytes when repeatedly running the same loop, or allow you to run arbitrary code between the definition and running of loops.
Finally, there are three ways of referring to variables, all of which are used in this program. The first is direct referencing, where the variable name is prefixed with a $
symbol. This accesses the value of the variable directly and returns it. The second is functional referencing, which doesn't have a prefixing character. This allows the code to distinguish between (potentially partial) functions assigned to variables, and actual variables containing a specific value. Finally, indirect referencing, prefixed with an @
symbol, creates a variable (if it doesn't already exist) and returns the variable object within a given scope. This allows you to create a loop variable (e.g. i
in for i in range(...)
).
How the actual solution works
Here is the ungolfed code:
n = elem = $Input;
var = 0;
while = While[{
mod = Modulo[$elem];
Not[mod[1]];
}];
while = while[{
for = For[4];
for = for[@index];
for = for[{
Print[$elem];
equal = Equal[$index];
if = If[{ equal[1]; }];
if = if[{ func = Times[$elem]; }];
Do[$if];
if = If[{ equal[2];}];
if = if[{ func = Add[$elem];}];
Do[$if];
if = If[{ equal[3];}];
if = if[{ func = Subtract[$elem];}];
Do[$if];
if=If[{ equal[4];}];
if=if[{ func = Divide[$elem];}];
Do[$if];
elem = func[var = Increment[$var]];
}];
Do[$for];
}];
Do[$while];
Try it online!
As you can see, it starts by assigning the three variables n
, e
and a
, which represent the input, the changing element in the sequence, and the modification number for each new element respectively. We then create a while loop:
w=While[{m=Modulo[$e];Not[m[1]];}];
The braces ({
and }
) define a block of code, where the final statement in the block is the condition for the while loop. In this case, we start by defining a partial modulo function, which will take in a second argument m
, and return e % m
. We then call this partial function with \$1\$ as its second argument, returning \$0\$ for integers and a non-zero integer for floats. We then calculate the logical not of this, mapping \$0 \to 1\$ and \$n \to 0, n \ne 0\$.
Next we come to the absolute monstrosity consisting of the while loop's body:
w=w[{f=For[4];f=f[@x];f=f[{Print[$e];q=Equal[$x];i=If[{q[1];}];i=i[{k=Times[$e];}];Do[$i];i=If[{q[2];}];i=i[{k=Add[$e];}];Do[$i];i=If[{q[3];}];i=i[{k=Subtract[$e];}];Do[$i];i=If[{q[4];}];i=i[{k=Divide[$e];}];Do[$i];e=k[a=Increment[$a]];}];Do[$f];}];
The primary part of this loop is a for loop, that iterates \$4\$ times each iteration of the while loop, has an iteration variable of x
and consists of:
Print[$e];
q=Equal[$x];
i=If[{q[1];}];i=i[{k=Times[$e] ;}];Do[$i];
i=If[{q[2];}];i=i[{k=Add[$e] ;}];Do[$i];
i=If[{q[3];}];i=i[{k=Subtract[$e] ;}];Do[$i];
i=If[{q[4];}];i=i[{k=Divide[$e] ;}];Do[$i];
e=k[a=Increment[$a]];
The first statement prints out each iteration of the sequence before modifying it. We then create a partial function to check equality with the loop variable x
, and encounter four if statements. Each statement checks if x
is equal to 1, 2, 3 or 4 respectively, and then assigns k
to each function in *
, +
, -
and /
, then makes it into a partial function with e
as its argument. Finally, we assign e
to k
run with a
as its second argument, and increment a
.
May we instead return an infinite list of the sequence? Also, is the output for 1 correct? I had something different after the 6. – cole – 2019-10-02T06:11:12.323
3@cole Since the sequence ends I don't think you can output an infinite list. – Post Rock Garf Hunter – 2019-10-02T06:13:09.203
1May we output 1 indexed, i.e. skip the first element? – Jo King – 2019-10-02T06:19:13.530
1No, the entire sequence must be printed. – infinitezero – 2019-10-02T06:20:36.250
May we print integers as floats?
1.0, 1.0, 2.0, 0.0, 0.0, 6.0, -1.0
etc – Jitse – 2019-10-02T10:25:46.780Yes, this has already been done – infinitezero – 2019-10-02T10:31:07.567
Can we output in groups of 4 (i.e.
(21, 21, 23, 20)(5, 25, 31, 24)(3, 27, 37, 26)
)? – Kevin Cruijssen – 2019-10-02T11:24:20.6501Yes you may @KevinCruijssen – infinitezero – 2019-10-02T12:05:32.653
Thanks for the accept but (assuming you're awarding it to the shortest solution by language), I'd rather it went to GB. – Shaggy – 2019-11-10T22:45:13.300