Your very own "for" instruction

38

7

Your very own "for" instruction

Assuming you have the following input : a, b, c, d

Input can be in one-line using any format "a/b/c/d" or "a,b,c,d" etc..

You can also have 4 inputs.

You must code the following behaviour (pseudo-code here) :

var i = <a>
while (i <b> <c>)
    print i
    i = i + <d>
    print "\n"

Here are some tests cases :

input : 1,<,10,1
output :
1
2
3
4
5
6
7
8
9

One more :

input : 20,>,10,1
output :
20
21
22
23
24
25
26
27
...
infinite loop / program crashes
  • a is an integer, the initial value of i.

  • b is a string or a char, it can't be something else, the comparator used in the ending condition of the for loop.

    b can and must be one of the following strings :

    - ">"
    - "<"
    
  • c is an integer, the number used in the ending condition of the for loop.

  • d is an integer that is added to i at every loop.

This is code-golf, the shortest answer wins !

Sygmei

Posted 2017-01-26T13:37:29.157

Reputation: 1 137

1Can the numbers be returned from a function as a list/sequence, rather than printed to stdout? – smls – 2017-01-26T17:07:51.257

@smls Nope sorry, the output must be like the examples ! – Sygmei – 2017-01-26T20:37:22.510

1It says my code should follow the pseudo-code and there's a print "\n", but I am using javascript's alert for each line. Would that be acceptable, or would I have to use console.log instead making my answer longer? – None – 2017-01-27T10:46:43.390

2You can use the alert function as a way to ouput but you can't use multiple alerts. Something like alert("23\n24\n25"); would work whereas alert("23"); alert("24"); alert(25); wouldn't – Sygmei – 2017-01-27T10:56:15.877

Answers

25

JavaScript (ES6),  44  43 56 bytes

Saved 1 byte thanks to ETHproductions
Edit: fixed to comply with output requirements

(a,b,c,d)=>{for(s='';eval(a+b+c);a+=d)s+=a+`
`;alert(s)}

Test

let f =

(a,b,c,d)=>{for(s='';eval(a+b+c);a+=d)s+=a+`
`;alert(s)}

f(1,'<',7,2)

Arnauld

Posted 2017-01-26T13:37:29.157

Reputation: 111 334

Nice use of scope! – ETHproductions – 2017-01-26T13:46:53.327

I think you can rearrange the eval to save a byte: (a,b,c,d)=>{for(;eval(a+b+c);a+=d)alert(a)} – ETHproductions – 2017-01-26T13:48:53.523

@ETHproductions Ah, yes. Nice one! – Arnauld – 2017-01-26T13:52:45.857

5That's a 44 with a tutu! – aross – 2017-01-26T16:24:23.877

This doesn't follow the specification where output is line-by-line with U+000A after every line. – Joey – 2017-01-27T10:36:10.880

@Joey I last edited this before it was an explicit requirement, so I'm not sure I'm absolutely required to comply to the updated rules. I don't know the exact policy, though, so that's fixed anyway. – Arnauld – 2017-01-27T12:42:36.123

Hm, hard to tell in hindsight from the edit history of the question. For my taste it's still not very well specified and comes down mostly to »Do whatever you want, as long as it vaguely resembles the task«. I guess I like having stricter task descriptions in general and I also like a correctness-first approach to solutions. Back when I used to post tasks here I nearly always supplied test scripts that could be used to unambiguously decide whether a solution was passing or not. – Joey – 2017-01-27T13:49:01.893

17

Javascript (ES6), 47 42 48 Bytes

Wanted to make the for version but someone was faster, so here's the recursive version.

(b,c,d)=>F=a=>eval(a+b+c)&&console.log(a)|F(a+d)

You need to add f= before and call it like f(b,c,d)(a).

Many thanks to Arnauld for the awesome golf.

alert changed to console.log because of output specification

user64039

Posted 2017-01-26T13:37:29.157

Reputation:

@Arnauld Thanks, that's a pretty cool golf. I just asked him, so let's see if he accepts it. – None – 2017-01-26T15:20:48.873

Glad to see it accepted. ;) – Arnauld – 2017-01-26T15:44:43.337

This doesn't follow the specification where output is line-by-line with U+000A after every line. – Joey – 2017-01-27T10:36:22.893

@Joey That's just pseudo-code, but I'll ask OP about this. – None – 2017-01-27T10:47:37.720

@Masterzagh: There was a question about alternative output formats already which was denied. – Joey – 2017-01-27T10:49:19.317

15

Pure bash, 35

I assume its OK just to plug the parameters into the standard for loop:

for((i=$1;i$2$3;i+=$4));{ echo $i;}

Try it online.

Digital Trauma

Posted 2017-01-26T13:37:29.157

Reputation: 64 644

Haha, bash makes it really easy – Sygmei – 2017-01-26T20:39:13.453

13

Jelly, 12 bytes

Ṅ+⁶µ⁴;⁵¹vµ¿t

Try it online!

Jelly has a lot of ways to tersely do iteration, create ranges, etc.. However, mirroring C++'s behaviour exactly is fairly hard, due to special cases like the increment being 0, the loop ending before it starts (due to the inequality being backwards), and the increment going in the wrong direction (thus meaning the exit condition of the loop can't be met naturally). As such, this solution is basically a direct translation of the C++, even though that makes it rather more low-level than a Jelly program normally is. Luckily, C++ has undefined behaviour on signed integer overflow (the question uses int), meaning that a program can do anything in that case, and thus there's no need to try to mimic the overflow behaviour.

Explanation

Ṅ+⁶µ⁴;⁵¹vµ¿t
   µ     µ¿   While loop; while ((⁴;⁵¹v) counter) do (counter = (Ṅ+⁶)counter).
    ⁴;⁵       Second input (b) appended to third input (c), e.g. "<10"
        v     Evaluate, e.g. if the counter is 5, "<10" of the counter is true
       ¹      No-op, resolves a parser ambiguity
Ṅ             Output the counter, plus a newline
 +⁶           Add the fourth input (d)
           t  Crashes the program (because the counter is not a list)

Crashing the program is the tersest way to turn off Jelly's implicit output (otherwise, it would output the final value of the counter); it generates a bunch of error messges on stderr, but we normally consider that to be allowed.

Incidentally, the loop counter is initialised with the current value before the loop starts. As the loop appears at the start of the program, that'll be the first input.

user62131

Posted 2017-01-26T13:37:29.157

Reputation:

You could change t to to have no crash. The dequeue results in an empty list for which Jelly's implicit print yields nothing. – Jonathan Allan – 2017-01-26T15:19:55.990

@JonathanAllan: It doesn't, what it actually does is to create a range from 2 to the given value, which is definitely visible on an implicit print. – None – 2017-01-26T16:01:47.527

Ah, I must've tested that theory with a loop ending in negative territory; indeed a range is implicitly created. – Jonathan Allan – 2017-01-26T16:26:48.260

Uhm, this is 12 characters, but it's not 12 bytes right? – Cruncher – 2017-01-27T22:44:50.577

@Cruncher: Jelly uses its own encoding in which each character used by the language is represented by a single byte (it only uses 256 different characters). The reason it doesn't use something better-known like code page 437 is to make it easier to type (I mean, it's not that easy to type, but it's easier than a language like gs2 would be). A hexdump of this program would be 12 bytes long.

– None – 2017-01-27T23:26:49.687

Ahhh okay that's cool :) – Cruncher – 2017-01-28T02:20:55.333

12

Python 2, 50 bytes

a,b,c,d=input()
while eval(`a`+b+`c`):print a;a+=d

Try it online!

Rod

Posted 2017-01-26T13:37:29.157

Reputation: 17 588

10

R, 63 bytes

function(a,b,c,d)while(do.call(b,list(a,c))){cat(a,"\n");a=a+d}

Sven Hohenstein

Posted 2017-01-26T13:37:29.157

Reputation: 2 464

9

Java, 58 bytes

(a,b,c,d)->{for(;b>61?a>c:a<c;a+=d)System.out.println(a);}

Roman Gräf

Posted 2017-01-26T13:37:29.157

Reputation: 2 915

14Is there a reason to create i? Could you skip the initialization part and just use a? Also, using the ASCII value of '>' (62) saves a byte. – Riley – 2017-01-26T14:22:12.820

6Following Riley's comment, you can do b>61 – user41805 – 2017-01-26T16:55:13.163

I don't believe this compiles. – ChiefTwoPencils – 2017-01-28T21:06:14.727

@ChiefTwoPencils It's a function. You have to write a test program around it in order to compile it. – wizzwizz4 – 2017-01-29T18:42:00.123

@wizzwizz4, obviously. But that still doesn't work. Give it a shot. Plus, my understanding is all bytes required to run it counts. – ChiefTwoPencils – 2017-01-30T23:49:08.117

@ChiefTwoPencils That's only programs, not functions. This is an anonymous function, so you'll need to assign it to a variable then call it with the necessary parameters. (Unless you mean that there are syntax errors, which is possible, but it looks to me like perfectly valid Java code (and even C code, excluding anonymous function and System.out.)) – wizzwizz4 – 2017-01-31T18:21:56.300

As mentioned by Riley & KritixiLithos, you don't need i. In addition, you can change b=='>' to b>61. So it becomes: (a,b,c,d)->{for(;b>61?a>c:a<c;a+=d)System.out.println(a);} (58 bytes) @ChiefTwoPencils (See the link to see how you can compile and run this.)

– Kevin Cruijssen – 2017-06-07T09:29:38.790

7

SmileBASIC, 53 bytes

INPUT A,B$,C,D
S=ASC(B$)-61WHILE S*A>S*C?A
A=A+D
WEND

Explanation:

INPUT A,B$,C,D
IF B$=="<" THEN S=-1 ELSE S=1 'get comparison direction
I=A
WHILE S*I>S*C 'loop while I is less than/greater than the end
 PRINT I
 INC I,D
WEND

This uses the fact that X<Y is the same as -X>-Y

12Me21

Posted 2017-01-26T13:37:29.157

Reputation: 6 110

I'll trust you for this one, I don't have a 3DS to test :) – Sygmei – 2017-01-26T13:52:01.380

I have Petit Computer, so cool idea! I will try something like this sometime... – python-b5 – 2017-01-26T21:24:20.883

You could use a READ statement, saving 1 byte. – ckjbgames – 2017-01-26T22:06:39.453

@ckjbgames how? – 12Me21 – 2017-01-26T22:08:04.060

@12Me21 Check the SmileBASIC manuals. It should be in the list of instructions for SmileBASIC. – ckjbgames – 2017-01-26T22:24:01.463

I know how READ works, but where would I use it in this program? – 12Me21 – 2017-01-26T22:26:31.133

@12Me21 Where the INPUT statement is. – ckjbgames – 2017-01-27T16:35:14.347

I don't think that's allowed, since you'd have to edit the file to change the DATA. – 12Me21 – 2017-01-27T16:55:10.373

7

05AB1E, 22 20 bytes

[D²`'>Q"‹›"è.V_#D,³+

Try it online!

Explanation

[                       # start loop
 D                      # copy top of stack (current value of a)
  ²`                    # push b,c to stack
    '>Q                 # compare b to ">" for equality
       "‹›"             # push this string
           è            # index into the string with this result of the equality check
            .V          # execute this command comparing a with c
              _#        # if the condition is false, exit loop (and program)
                D,      # print a copy of the top of the stack (current value of a)
                  ³+    # increment top of stack (a) by d

Emigna

Posted 2017-01-26T13:37:29.157

Reputation: 50 798

1Any input format is accepted so the second version is okay :) – Sygmei – 2017-01-26T15:09:36.887

6

Stacked, 34 bytes

@d@c@b[show d+][:c b tofunc!]while

Try it online! (Testing included.) This is a function that expects the stack to look like:

a b c d

For example:

1 '<' 10 2
@d@c@b[show d+][:c b tofunc!]while

Explanation

@d@c@b[show d+][:c b tofunc!]while
@d@c@b                               assign variables
               [............]while   while:
                :c                   duplicate "i" and push c
                   b tofunc!         convert b to a function and execute it
      [.......]                      do:
       show                          output "i" without popping
            d+                       and add the step to it

Conor O'Brien

Posted 2017-01-26T13:37:29.157

Reputation: 36 228

4

C++, 80

Whoops, this is C++ not C. Was a bit confused by the question.

void f(int a,char b,int c,int d){for(;b==62?a>c:a<c;a+=d)cout<<a<<endl;}

Roman Gräf

Posted 2017-01-26T13:37:29.157

Reputation: 2 915

Is this C or C++? – betseg – 2017-01-26T14:00:19.170

10Which implementation of C++? (I'm curious how you're getting something akin to using namespace std for free). – H Walters – 2017-01-26T14:13:15.440

Doesn't i have to start at a, not 0? You can just use a and skip i altogether and use the ASCII value of '>'. for(;b==62?a>c:a<c;a+=d) – Riley – 2017-01-26T14:18:59.110

Doesn't work for f(1,'<'3,1); – Roman Gräf – 2017-01-26T14:34:51.643

Ack... yeah, requires the math on both sides; for(b-=61;b*a>b*c;a+=d) works for a single byte; but so does for(;b-62?a<c:a>c;a+=d). – H Walters – 2017-01-26T14:46:34.143

...for another byte see my comment for gurka's C solution. – H Walters – 2017-01-26T16:04:25.813

(future reference:) b==62 could also be written as b>61, since < is 60. I'm assuming the input is always correct – Charlie – 2017-02-02T21:24:44.250

4

C, 52 51 bytes

-1 byte thanks to H Walters

f(a,b,c,d){for(;b&2?a>c:a<c;a+=d)printf("%d\n",a);}

Try it online!

simon

Posted 2017-01-26T13:37:29.157

Reputation: 351

1Sorry for the mistake in the pseudo-code, i increments after each print :) – Sygmei – 2017-01-26T15:57:14.943

1Use b&2 instead of b^60 for another byte. – H Walters – 2017-01-26T16:02:21.093

4

Python 3, 52 bytes

def f(a,b,c,d):
 while[a>c,a<c][b<'>']:print(a);a+=d

repl.it

Jonathan Allan

Posted 2017-01-26T13:37:29.157

Reputation: 67 804

Clever use of lists ! – Sygmei – 2017-01-26T20:42:39.470

4

Pip, 14 bytes

W Va.b.ca:d+Pa

Takes four command-line arguments. Supports negative & floating point numbers and comparison operators < > = <= >= !=. Try it online!

                a,b,c,d are cmdline args
W               While loop with the following condition:
  Va.b.c          Concatenate a,b,c and eval
            Pa  Print a with newline (expression also returns value of a)
        a:d+    Add d to that and assign back to a

DLosc

Posted 2017-01-26T13:37:29.157

Reputation: 21 213

4

Jelly, 8 bytes

ḢṄ+⁹;µV¿

This is a dyadic link that takes a,b,c as its left argument and d as its right one. Output may be infinite and goes to STDOUT.

Try it online!

How it works

ḢṄ+⁹;µV¿  Dyadic link.
          Left argument:  a,b,c (integer, character, integer)
          Right argument: d     (integer)

       ¿  While...
      V     the eval atom applied to a,b,c returns 1:
     µ       Combine the links to the left into a chain and apply it to a,b,c.
Ḣ              Head; pop and yield a from a,b,c.
 Ṅ             Print a, followed by a linefeed.
  +⁹           Add a and the right argument (d) of the dyadic link.
    ;          Concatenate the result and the popped argument of the chain,
               yielding a+d,b,c.

Dennis

Posted 2017-01-26T13:37:29.157

Reputation: 196 637

Command-line arguments use Python syntax and cannot distinguish between a character and a singleton string. If you want to use CLAs, you have to insert an F to flatten the array. – Dennis – 2017-01-26T23:47:32.770

2Now I want to delete half my comment as it's obsolete, whilst keeping the other half. I guess I'll just repeat the relevant half and delete the rest: "Oh, bleh, you defined it as a function so you could disregard the implicit output under PPCG rules. I should have thought of that." – None – 2017-01-26T23:56:23.213

4

Python 2, 45 bytes

exec"i=%d\nwhile i%c%d:print i;i+=%d"%input()

Try it online!

A very literal implementation of the spec. Takes the code template, substitutes in the inputs via string formatting, and executes it.

xnor

Posted 2017-01-26T13:37:29.157

Reputation: 115 687

4

Plain TeX, 88 bytes

\newcount\i\def\for#1 #2 #3 #4 {\i#1\loop\the\i\endgraf\advance\i#4\ifnum\i#2#3\repeat} 

The command \for provides the requested function. Save this as for.tex and then run it and enter the variable values at the command line: pdftex '\input for \for 1 < 5 1 \bye' The variable values must be separated by spaces.

musarithmia

Posted 2017-01-26T13:37:29.157

Reputation: 531

4

Python 3, 61 bytes

One liner:

e=input;exec(f'i={e()}\nwhile i{e()}{e()}:print(i);i+={e()}')

G-Ox7cd

Posted 2017-01-26T13:37:29.157

Reputation: 41

Welcome to the site! Nice use of the new literal string interpolation feature. I think you might be able to save a byte by replacing \t with a space. – 0 ' – 2017-01-28T05:56:11.093

Thank you.still the same size after removing the \n\t after third e() – G-Ox7cd – 2017-01-28T06:37:40.480

3

Haskell, 66 64 bytes

f a b c d|last$(a<c):[a>c|b>"<"]=print a>>f(a+d)b c d|1<3=pure()

Try it online! Usage:

Prelude> f 0 "<" 9 2
0
2
4
6
8

Laikoni

Posted 2017-01-26T13:37:29.157

Reputation: 23 676

3

Common Lisp, 82 80 79 73 64 bytes

(defmacro f(a b c d)`(do((i,a(+ i,d)))((not(,b i,c)))(print i)))

Test

(f 1 < 10 1)

1 
2 
3 
4 
5 
6 
7 
8 
9 
NIL
CL-USER> 

-9 bytes thanks to PrzemysławP.

coredump

Posted 2017-01-26T13:37:29.157

Reputation: 6 292

Perhaps you can save 9 bytes, by defining a macro. (defmacro f(a b c d)<insert backqoute here>(do((i,a(+ i,d)))((not(,b i,c)))(print i))) Usage: (f 1 < 10 1) – None – 2017-05-01T22:55:39.227

@PrzemysławP Thanks again ! – coredump – 2017-06-07T08:24:19.030

3

Ruby, 43 41 bytes

->a,*i,d{a=d+p(a)while eval"%s"*3%[a,*i]}

If b can be taken in as a Ruby symbol instead of a string, you get 38 bytes:

->a,b,c,d{a=d+p(a)while[a,c].reduce b}

Try either solution online!

Value Ink

Posted 2017-01-26T13:37:29.157

Reputation: 10 608

3

PHP, 69 65 bytes

for(list(,$i,$b,$c,$d)=$argv);$b<"="?$i<$c:$i>$c;$i+=$d)echo"$i
";

Run with '-r'; provide command line arguments as input.

For just one byte more 4 more bytes, I can take every operator:

for(list(,$i,$b,$c,$d)=$argv;eval("return $i$b$c;");$i+=$d)echo"$i
";

Yeah, evil eval. Did you know that it can return something?


Shorthand destructuring [,$i,$b,$c,$d]=$argv; would save 4 more bytes;
but PHP 7.1 postdates the challenge.

Titus

Posted 2017-01-26T13:37:29.157

Reputation: 13 814

Neat ! I wasn't sure when creating the challenge if I should include every common operators, then I remembered that they aren't all the same (~= for != in Lua for example) – Sygmei – 2017-01-26T20:55:52.903

Woah, eval IS evil. – cyberbit – 2017-01-27T15:29:05.887

It seems to me that you can use PHP 7.1 to make it shorter. If it is not so the use of list saves 4 Bytes plus 4 Bytes with short syntax – Jörg Hülsermann – 2017-06-07T11:32:15.850

@PHP 7.1 postdates the challenge; but thanks for list(). – Titus – 2017-06-07T16:23:26.813

3

Bash (+Unix Tools), 29 bytes

Golfed

bc<<<"for(x=$1;x$2$3;x+=$4)x"

Test

./forloop 1 '<' 10 1
1
2
3
4
5
6
7
8
9

zeppelin

Posted 2017-01-26T13:37:29.157

Reputation: 7 884

1Ha. I was just about to post the exact same thing! +1 – Digital Trauma – 2017-01-26T22:07:32.730

2

Groovy, 51 bytes

{a,b,c,d->while(Eval.me("$a$b$c")){println a;a+=d}}

This is an unnamed closure. Try it Online!

Caution - If you want to test this with groovy console, make sure you kill the entire process when the input causes an infinite loop. I noticed this after it consumed ~5 gigs of RAM.

Gurupad Mamadapur

Posted 2017-01-26T13:37:29.157

Reputation: 1 791

2

Perl 6, 44 bytes

{.say for $^a,*+$^d...^*cmp$^c!= $^b.ord-61}

How it works

{                                          }  # A lambda.
          $^a                                 # Argument a.
             ,*+$^d                           # Iteratively add d,
                   ...^                       # until (but not including the endpoint)
                       *cmp$^c                # the current value compared to c
                                              # (less=-1, same=0, more=1)
                              != $^b.ord-61.  # isn't the codepoint of the b minus 61.
 .say for                                     # Print each number followed by a newline.

If it's okay to return a (potentially infinite) sequence of numbers as a value of type Seq, instead of printing the numbers to stdout, the .say for part could be removed, bringing it down to 35 bytes.

smls

Posted 2017-01-26T13:37:29.157

Reputation: 4 352

2

Clojure, 66 63 bytes

#(when((if(= %2"<")< >)% %3)(println %)(recur(+ % %4)%2 %3 %4))

-3 bytes by factoring out the loop. I'm "abusing" the init parameter to act as the running accumulator.

Recursive solution (with TCO). See comments in pregolfed code. I tried a non-TCO recursive solution, and it ended up being 67 bytes.

I'd love to see this beat in Clojure! I think this is the smallest I can get it.

(defn my-for [init-num com-str com-num inc-num]
  (let [op (if (= com-str "<") < >)] ; Figure out which operator to use
    (when (op init-num com-num) ; When the condition is true, print and recur
      (println init-num)
      (recur (+ init-num inc-num) com-str com-num inc-num))))
    ; Else, terminate (implicit) 

Carcigenicate

Posted 2017-01-26T13:37:29.157

Reputation: 3 295

Oh I didn't notice this answer. #(when(({">">"<"<}%2)% %3)(println %)(recur(+ % %4)%2 %3 %4)) would be 61 bytes, combining your when with my ({">">"<"<}%2). – NikoNyrh – 2017-01-26T19:23:27.437

2

Clojure, 66 bytes

#(loop[i %](if(({">">"<"<}%2)i %3)(do(println i)(recur(+ i %4)))))

This could have been 55 bytes as< and > are functions in Clojure:

(def f #(loop[i %](if(%2 i %3)(do(println i)(recur(+ i %4))))))
(f 1 < 10 1)

NikoNyrh

Posted 2017-01-26T13:37:29.157

Reputation: 2 361

I like the use of the map here. I would have never thought that that would have beaten my way. Also interesting that both of our initial counts were the same, despite slightly different approaches. – Carcigenicate – 2017-01-26T20:30:52.773

Allowing b to be a function would give an unfair advantage to some languages :) – Sygmei – 2017-01-26T20:40:18.507

True, but I think most languages I know of wouldn't benefit much from allowing < instead of "<", except Clojure. – NikoNyrh – 2017-01-26T20:43:28.333

@Sygmei True. It would be freakin sweet though. Can't blame you making that call. – Carcigenicate – 2017-01-26T20:43:51.137

OP said characters are fine instead of strings for the comparison operators btw. That should save a couple bytes. – Carcigenicate – 2017-01-26T20:44:17.900

Can't Haskell use that advantage too ? – Sygmei – 2017-01-26T20:45:25.697

I don't know Haskell :( Using strictly chars doesn't help because {\> >\< <} is same length as {">">"<"<}. {\>>\<<} isn't parsed correctly at least on Nightcode. Using symbols < and > is shown in the 55 byte example already. – NikoNyrh – 2017-01-26T20:47:50.483

@Sygmei Idk exactly how the Haskell answer works. It potentially allows for some compression in Clojure because the character for "less than" is \<, which is 1 character shorter than a string representation of "<". Whether or not you gain from that depends on the situation unfortunately. – Carcigenicate – 2017-01-26T22:08:28.437

2

QBIC, 51 40 bytes

:;::{?a┘a=a+c~A=@<`|~a>=b|_X]\~a<=b|_X

And three minutes after posting I realised I could simplify the terminator logic...

:;::      Consecutively read a, A$, b and c from the command line
{?a┘      Start an infinite loop; print a, add a newline to the source
a=a+c     increment a
~A=@<`|   If we are in LESS THAN mode
  ~a>=b   and IF we are no longer LESS
    |_X]  THEN QUIT, end if.
  \       ELSE (we're in GREATER THAN mode)
    ~a<=b IF we are no longer GREATER
    |_X   THEN QUIT
          The last IF and the loop are auto-closed

steenbergh

Posted 2017-01-26T13:37:29.157

Reputation: 7 772

2

Batch, 94 bytes

@set i=%1
@set o=gtr
@if "%~2"=="<" set o=lss
:g
@if %i% %o% %3 echo %i%&set/ai+=%4&goto g

If it wasn't for the second parameter behaviour, it could be done in 53 bytes:

@for /l %%i in (%1,%4,%n%)do @if not %%i==%3 echo %%i

This simply does nothing if the step has the wrong sign. The extra test is because Batch's for loop allows the loop variable to equal the end value.

Neil

Posted 2017-01-26T13:37:29.157

Reputation: 95 035

2

TI-Basic, 41 34 bytes

Prompt A,Str2,Str3,D
While expr("A"+Str2+Str3
Disp A
A+D->A
End

Timtech

Posted 2017-01-26T13:37:29.157

Reputation: 12 038

1The way that a TI calculator works, many symbols are stored as a single byte. Prompt, Str2, Str3, While, expr(, Disp, ->, and End are all single-byte symbols. I count 29 bytes. – Pavel – 2017-01-27T00:14:21.083

@Pavel Thanks for your interest! Although it's true that TI-Basic is tokenized, not all tokens are one byte. For example, Str2, Str3, and expr( are all two-byte tokens. To see a list of one-byte tokens, check out http://tibasicdev.wikidot.com/one-byte-tokens

– Timtech – 2017-01-27T01:42:08.507

2

dc, 47 bytes

dc, 48 bytes

Also Bash + Unix utilities, 29 bytes

dc (47 bytes):

1sb[_1sb]s zz?sdlb*sc[pld+lnx]sl[dlb*lcr<l]dsnx

Try it online!

Note that negative numbers must be entered with an underscore instead of a minus sign, because that's how dc accepts numeric input. So write, for example, _5 instead of -5.


dc can't read character or string input into a variable and process it (there's a more detailed explanation below), but I found two ways of working around this:

The 47-byte dc solution works on input that has argument1 and argument2 reversed, with spaces as the delimiter. So counting from 1 up to (but not including) 10 in steps of 3 would be entered as:

< 1 10 3

If it's not acceptable to change the order of the arguments, I also give a 48-byte dc solution which keeps the original order of the arguments. This one uses zz as the delimiter between arguments. So counting from 1 up to (but not including) 10 in steps of 3 again would use the following input line:

1zz<zz10zz3

Finally, the same ideas yield a 29-byte bash solution.


Details on dc's lack of string processing, and how this program deals with that:

Handling this problem in dc is tricky, because dc doesn't accept string or char input as most languages do. When dc reads an input string, it immediately runs that string as a dc program (a macro), and then discards the string. You can't store the characters of the string in memory and process them later, or in any other way. This interferes with the requirement to have '<' or '>' in the input.

I'll show two ways around this. In the solution above (47 bytes), we switch the order of the first two inputs. The input delimiter is the space character. For example, to count from 1 up to (but not including) 10 in steps of 3, you'd input

< 1 10 3

Here's the idea behind this solution:

Macros in dc are stored in registers, and registers have single-character names. I store a macro in the register whose name is just a space character.

The program works by pushing a 0 and 1 on the stack before getting the input. Then, when the input is run as a dc program (which is what dc does with input lines), the '<' or '>' character is executed as a command, which is a conditional macro execution of the macro whose name is the next char after the '<' or '>'. Specifically, the top two items on the stack are popped. If the first item popped is < (respectively, >) the second item popped, the indicated macro is executed. The next character (after the '<' or '>') is a space, so the macro that we've stored in the register whose name is the space char is the one executed if the condition holds. But we had pushed 0 and 1 on the stack, so the first item popped was a 1, and the second item popped was a 0. As a result, the macro is executed only if the conditional test was >, not <. This lets us distinguish between '<' and '>' in the input.

The remaining items in the line are just numbers, and dc will simply push those numbers, in turn, on the stack.

Here's a detailed description. Most of the time, the counting variable (i in the pseudocode in the problem statement) is stored at the top of the stack.

1sb             Store 1 in register b.  (b will end up being 1 for '<', and -1 for '>').
[_1sb]s         Note that there is a space after the second s.  So the space char is the name of a macro which stores -1 in b.
z               Push 0 on the stack.
z               Push 1 on the stack.
?               Accept input in the format above.  This will:
                    - Store 1 or -1 in b, depending on whether you've typed "<" or ">"
                    - Push each of the three numbers in turn on the stack.
sd              Save the increment in register d.
lb*sc           Save either limit or -limit in register c, depending on whether the input started with "<" or ">".
[pld+lnx]sl     Define a macro called l which is the body of our loop:
                    - Prints the top of the stack
                    - Adds the increment to the top of the stack.
                    - Calls macro n (the loop test).

 [dlb*lcr<l]dsn  Define a macro called n which is the test of the loop:
                    It checks to see if i (at the top of the stack) times b is less than c; if so, it calls macro l (looping back).
 x               Execute the loop test macro initially (a while loop needs to have a test at the top before entering the loop the first time).

On the other hand, the OP stated:

Input can be in one-line using any format "a/b/c/d" or "a,b,c,d" etc.

So maybe it isn't legitimate to switch the order and require b before a in the input.

Here's an alternative which keeps a, b, c, and d in their original order. We are allowed to use any delimiter; I'll use zz as the delimiter. So counting from 1 up to (but not including) 10 in steps of 3 would be entered as:

1zz<zz10zz3

The new program, with zz-delimited input, is

dc (48 bytes):

1sb[_1sb]sz?sdiilb*sci[pld+lnx]sl[dlb*lcr<l]dsnx

This is one byte longer than the 47-byte first solution.

Try the zz-delimited version online!

I personally think the different-order < 1 10 3 formatting is more in the spirit of the problem, but maybe 1zz<zz10zz3 better meets the actual technical specification.

You could probably get a shorter solution if you allowed different delimiters between the different input arguments, but I don't think that's in the spirit of the problem.

Bash + Unix utilities, 29 bytes

You can turn the underlying idea above into a bash program (which calls dc); this avoids all the difficulties with "<" and ">", and it also simplifies handling the various numeric parameters, so it's only 29 bytes long, the same as @zeppelin's bash+bc answer.

bash version (29 bytes):

dc -e[p$4+d$3r$2l]sl$1d$3r$2l

Try the bash version online!

Here's a description of how the dc program inside the bash program works:

The value of i is stored at the top of the stack most of the time.

[      Start of macro (i is at the top of the stack). This macro will be called l.
p      Print i
$4+    i += (4th argument)
d      Duplicate i at the top of the stack.
$3     Push the 3rd argument onto the stack.
r      Swap the top two items on the stack, so i is at the top and arg3 is second
$2l    $2 is "<" or ">", causing the top two items to be popped from the stack, and macro l is then called (effectively looping back) if i < arg3 or i > arg3, respectively.
]sl    End of macro definition; store macro in register l.

$1     Push argument 1 onto the stack (i = 1st argument).
d$3r$2l Just as above, call macro l if i < arg3, or i > arg3, depending on whether arg2 is "<" or ">"

Mitchell Spector

Posted 2017-01-26T13:37:29.157

Reputation: 3 392

2

tcl, 52

proc F {a b c d} {while \$a$b$c {puts $a;incr a $d}}

demo

sergiol

Posted 2017-01-26T13:37:29.157

Reputation: 3 055

How is this using d to decide by how much to increment a? – Paŭlo Ebermann – 2017-01-28T13:03:06.770

@PaŭloEbermann: My mistake! UPDATED! – sergiol – 2017-01-28T13:05:47.463

1

Pari/GP , 48 Bytes

f(a,b,c,d)=while(eval(Str(a,b,c)),print(a);a+=d)

Testing

f(4,"<",7,1)  \\ input
4             \\ output
5
6

Gottfried Helms

Posted 2017-01-26T13:37:29.157

Reputation: 201

1

C#, 77 bytes

(a,b,c,d)=>{for(int i=a;b==">"?i<c:i>c;i+=d){System.Console.Write(i+"\n");}};

Horváth Dávid

Posted 2017-01-26T13:37:29.157

Reputation: 679

1

F#, 71 106 97 bytes

fun a b c d->let i=ref a in while(b !i c)do printfn"%i%s"!i d;i:=!i+1;done

I didn't read the question fully!

fun a b c d->let i=ref a in while((if b='<'then(<)else(>))!i c)do printfn"%i%s"!i d;i:=!i+1;done

Cyclic3

Posted 2017-01-26T13:37:29.157

Reputation: 121

1

Ruby, 37 bytes

->a,b,c,d{(p a;a+=d)while a.send b,c}

A pretty straightforward solution. Unlike Value Ink's Ruby solution b doesn't have to be a Ruby symbol; just ints and a string/char as per the challenge. And it's still a byte under :)

Try it online

Flambino

Posted 2017-01-26T13:37:29.157

Reputation: 1 001

1

VBA, 87 Bytes

subroutine that does the thing

Sub f(a,b,c,d)
While IIf(b="<",a<c,a>c)
Debug.?a
a=a+d
Wend
End Sub

Taylor Scott

Posted 2017-01-26T13:37:29.157

Reputation: 6 709

0

APL (Dyalog), 19 bytes

{⍵⍺⍺⍨⊃⍺:⋄⍺∇2⊃⍺+⎕←⍵}

This is an operator taking (c,d) as left argument, b as left operand, and a as right argument.

{ anonymous "something"

 [if] the right argument

⍺⍺⍨ is not ber than (also signals that this is an operator)

⊃⍺ the first of the left arguments

: then terminate

else

⍺∇ reuse the left argument to call the derived function (this operator with its operand) on

2⊃ the second element of

⍺+ the left argument added to

⎕← the printed

 right argument

}

Try it online!

Adám

Posted 2017-01-26T13:37:29.157

Reputation: 37 779

0

Excel VBA, 47 Bytes

Anonymous VBE immediate window function that takes input as described in prompt from the range [A1:D1] on the ActiveSheet object and implicitly outputs back onto that object by modifying the value of the visible [A1].Value variable

While[If(B1="<",A1<C1,A1>C1)]:[A1]=[A1+D1]:Wend

Taylor Scott

Posted 2017-01-26T13:37:29.157

Reputation: 6 709