26
\$\begingroup\$

Your task is to write a program or function. It's output/return value must follow these rules:

  • The program outputs 1
  • The program repeated n times outputs n
  • The program backwards outputs -1
  • The program backwards and repeated n times outputs -n
  • A mix of forward and backward programs will output number_forward - number_backward

Take the program aB for example.

  • aB should output 1
  • aBaB should output 2
  • Ba should output -1
  • BaBa should output -2
  • aBBa should output 0
  • aBBaBa should output -1
  • aaB, C, or would not need to be handled

This is , so shortest in bytes per language wins.

\$\endgroup\$
  • \$\begingroup\$ can you add test case aBBaaBBa ? \$\endgroup\$ – 榨 菜 Dec 16 '20 at 21:34
  • 1
    \$\begingroup\$ I'm not sure if the rules as given would allow 0+1-0 as a Python solution, relying on the interpreter to implicitly print out the result of an expression formed by concatenating that or its reverse some number of times. \$\endgroup\$ – Daniel Schepler Dec 17 '20 at 0:30
  • 5
    \$\begingroup\$ @DanielSchepler 0+1-0 is a great idea for an answer. You just need to pick the right language, e.g. tio.run/##y0osKPn/30DXUNvg/38A \$\endgroup\$ – Digital Trauma Dec 17 '20 at 2:51
  • 1
    \$\begingroup\$ @DigitalTrauma you should post that as an answer! \$\endgroup\$ – pxeger Dec 17 '20 at 9:31
  • 1
    \$\begingroup\$ @DanielSchepler if you open a duplicate answer to this, I will happily delete this one. The credit should go to you. \$\endgroup\$ – Digital Trauma Dec 17 '20 at 16:27

26 Answers 26

23
\$\begingroup\$

Jelly, 2 bytes

NC

Try it online! Or see all test-cases.

How?

In Jelly any sequence of monadic atoms forms a monadic chain which simply applies those monadic atoms in turn from left to right, starting with the value of it's left argument. When a full program is run with no arguments zeros are implicitly supplied as necessary, i.e. main_link(0) is called. As such NC is C(N(0)) and CN is N(C(0)).

NCNC ... CN ... NC - Main Link: no arguments
N                  - negate((implicit)0)     -1 *  0 =  0
 C                 - complement(that)         1 -  0 =  1
  N                - negate(that)            -1 *  1 = -1
   C               - complement(that)         1 - -1 =  2
     ...           - 
     ...           -                             ... =  a
        C          - complement(a)            1 -  a =  1 - a
         N         - negate(that)       -1 * (1 - a) =  a - 1
            ...    - 
            ...    -                             ... =  b
               N   - negate(b)               -1 *  b = -b
                C  - complement(that)         1 - -b =  b + 1
\$\endgroup\$
13
\$\begingroup\$

Jelly, 3 bytes

I wonder if 2 bytes is possible in some language (I suspect that'd require it to consider the parity of the positions of the commands).

‘ḷ’

Explanation: increments, decrements, and takes the left one, and for some magic reasons, when repeated, the program works as requested. Try it online!

\$\endgroup\$
  • \$\begingroup\$ what in the world... \$\endgroup\$ – Razetime Dec 16 '20 at 15:13
  • \$\begingroup\$ Do Jelly programs take 0 as a default when expecting a number but none is given? Curious how that works. \$\endgroup\$ – xnor Dec 16 '20 at 15:14
  • 2
    \$\begingroup\$ @xnor I have no idea how Jelly works :P I just remembered that an empty program outputs 0, and assumed that 0 is the default value for everything (which seems to be true) (and the syntax of using three functions in a row like this is the only thing I understood from the tutorial) \$\endgroup\$ – the default. Dec 16 '20 at 15:17
  • 4
    \$\begingroup\$ @xnor Yes, if a Jelly link is run niladically (without arguments), it assumes an argument of 0, except in a few specific circumstances \$\endgroup\$ – caird coinheringaahing Dec 16 '20 at 16:30
13
\$\begingroup\$

Bash, 39

Thanks to:

  • @pxeger for s/EXIT|TIXE/0/
  • @Sisyphus for s/0 # 0/0/

trap echo\ $[++a] 0 ]a--[$ \ohce part

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ maybe a newline would be necessary at the beginning for a backward followed by a forward \$\endgroup\$ – Nahuel Fouilleul Dec 16 '20 at 18:10
  • \$\begingroup\$ otherwise removing the # also works but writes on stderr, don't know if it's allowed \$\endgroup\$ – Nahuel Fouilleul Dec 16 '20 at 18:16
  • 2
    \$\begingroup\$ You can replace EXIT and TIXE with just 0 \$\endgroup\$ – pxeger Dec 16 '20 at 19:55
  • 1
    \$\begingroup\$ @Jonah Yes, that's right. So for example after arithmetic expansion, 2 forwards would effectively be trap 'echo 1' 0; trap 'echo 2' 0. \$\endgroup\$ – Digital Trauma Dec 16 '20 at 21:57
  • 1
    \$\begingroup\$ If you don't mind writing a bunch of junk to stderr then you can replace 0 # 0 with just 0, and the extra args are ignored. \$\endgroup\$ – Sisyphus Dec 16 '20 at 23:04
8
\$\begingroup\$

Perl 5 -0777p, 13 bytes


++$_;#;_$--

Try it online!

\$\endgroup\$
7
\$\begingroup\$

05AB1E, 4 bytes

¾¼.¾

Try it online - 1x forward: 1.
Try it online - 1x backwards: -1.
Try it online - 3x forward: 3.
Try it online - 3x backwards: -3.
Try it online - 1x forward + 1x backwards: 0.
Try it online - 2x forward + 5x backwards + 1x forward: -2.

Explanation:

The 1x forward program does the following:

¾     # Push the counter variable to the stack (0 by default)
 ¼    # Increment the counter variable
  .   # No-op, because `.¾` doesn't exist as 2-byte command, so it just ignores this
   ¾  # Push the counter variable to the stack (which is 1 now)
      # (implicitly output the top of the stack as result)

The 1x backward program does the following:

¾     # Push the counter variable to the stack (0 by default)
 .¼   # Decrement the counter variable
   ¾  # Push the counter variable to the stack (which is -1 now)
      # (implicitly output the top of the stack as result)

Any combination of these two programs after one another increments and decrements the counter variable, but only the last value pushed to the stack is output implicitly at the very end.

\$\endgroup\$
7
+500
\$\begingroup\$

R, 26 bytes

F+
1->F#F=FF
FF=F#F>-1-
+F

Try it online!

!enilno ti yrT

Twice backwards and four times forwards

A very different (and shorter) approach to Giuseppe's R answer (in which he predicted that this answer was coming!).

F is initially a shorthand for FALSE and so gets coerced to 0. When the program is run forwards, we use rightwards assignment to get F=F+1 and FF=F. When concatenated with itself, the program becomes

F+
1->F#F=FF
FF=F#F>-1-
+FF+
1->F#F=FF
FF=F#F>-1-
+F

Try it online!

and so the second time, we are doing F=+FF+1 which also increments F.

When run backwards, the only difference is that we use +-1 instead of +1.

When the final line is run, we print +F.

\$\endgroup\$
  • 1
    \$\begingroup\$ Well there ya go! Automatic line continuation is useful here too. I'll come back and bounty this once the question is eligible. \$\endgroup\$ – Giuseppe Dec 17 '20 at 15:14
  • 2
    \$\begingroup\$ Great! I tried for ages to get something like this to work, without success... Well done! \$\endgroup\$ – Dominic van Essen Dec 17 '20 at 19:52
7
\$\begingroup\$

Polyglot Japt, R, Applescript, 5 bytes

All credit for this one goes to @DanielSchepler. Daniel, if you open a duplicate answer to this, I will happily delete this one.

0+1-0

I don't know Japt at all, but this is just simple arithmetic evaluation. The result of the last evaluation is output at the end of the program by default. Japt was the first language that I found that satisfied this, but I'm sure there are others.

Forward (1): Try it online!

Forward-Backward-Backward-Forward-Forward-Backward-Backward (1):Try it online!

\$\endgroup\$
  • \$\begingroup\$ This is a brilliant answer! You (or Daniel) could label it a polyglot \$\endgroup\$ – user Dec 17 '20 at 16:37
  • 2
    \$\begingroup\$ Also works in R. \$\endgroup\$ – Robin Ryder Dec 17 '20 at 20:30
7
\$\begingroup\$

C++ (gcc), 324 325 323 bytes

Note the leading and trailing newlines.

Thanks to Jonathan Allen for spotting the need for a leading newline.


#ifndef M//
#define M(a,b)a##b//
#define W(z,x)M(z,x)//
#import<cstdio>//
int n;struct X{X(int d){n+=d;}};main(){printf("%d",n);}//
#endif//
X W(a,__LINE__)=1;//;1-=)__ENIL__,s(W X
//fidne#
//};)n,"d%"(ftnirp{)(niam;}};d=+n{)d tni(X{X tcurts;n tni
//>oidtsc<tropmi#
//)x,z(M)x,z(W enifed#
//b##a)b,a(M enifed#
//M fednfi#

Try it online!

aBaB (2)

Ba (-1)

BaBa (-2)

aBBa (0)

BaaB (0)

aBBaBa (-1)

Rundown

Comments are used to make the code legal in forward as well as reversed form.

#ifndef M//
...
#endif//

These are your basic guards to make sure we only define things once.

int n;struct X{X(int d){n+=d;}};main(){printf("%d",n);}//

Inside the guard we also declare the integer n, which will be automatically initialized to 0 by virtue of being a global, as well as define a struct X, whose constructor takes an integer value to add to the global n. The main() function simply prints the value of n.

main() is run after all global variables have been sorted out, so we use the declaring of globals as a way to alter that value of n before main() is entered.

This requires a way to declare an arbitrary amount of variables, leading to:

#define M(a,b)a##b//
#define W(z,x)M(z,x)//

The main magic of the stew: Helper macroes that allow the gluing of tokens together in a very useful way. Calling W(a,b) will yield the token ab, with the potent twist of evaluating b as a macro first, which makes these kinds of things possible:

#define M(a,b)a##b
#define W(z,x)M(z,x)
#define b 10
int W(a,b);          // This makes an int called "a10"

We combine this with the special preprocessor macro __LINE__ which always expands to the current line number, allowing us a way to produce an arbitrary amount of variables having unique names.

X W(a,__LINE__)=1;//;1-=)__ENIL__,s(W X

Suppose we are at line 553; this will then declare a variable a553 of type X, running its constructor with the argument 1. The reversed version is identical, save for using -1 instead.

Our preprocessor guards make sure the above line and its reverse are the only things repeated.

\$\endgroup\$
  • \$\begingroup\$ I think it needs a leading newline too. \$\endgroup\$ – Jonathan Allan Dec 17 '20 at 0:56
  • \$\begingroup\$ @JonathanAllan Ah, yes, indeed! \$\endgroup\$ – gastropner Dec 17 '20 at 1:01
5
\$\begingroup\$

Nim, 115 bytes


when not declared i:#1=-i
 var i=0;addQuitProc do:echo i#i ohce:od corPtiuQdda;0=i rav 
i+=1#:i deralced ton nehw

There is a leading and trailing newline. The second line has a trailing space.

Try it online!

Try it online!Try it online!Try it online!

!enilno ti yrT

!enilno ti yrT!enilno ti yrTTry it online!!enilno ti yrT

\$\endgroup\$
5
\$\begingroup\$

Ruby, 41 bytes


$.+=1;END{exit!p$.}#}.$p!tixe{DNE;1=-.$

Try it online!

\$\endgroup\$
5
\$\begingroup\$

R, 99 91 bytes


l=readLines();`*`=grepl;1+sum("^l"*l-"^r"*l)#1-)r*'r^'-r*'l^'(mus;lperg=`*`;)(seniLdaer=r

Try it online!

-8 bytes thanks to Dominic van Essen!

Tripled

Reversed

Forwards and Backwards

Yet another iteration on third time the charm.

R has an odd but often useful (and not just for golfing) feature where data can be stored in the code, and read in as such. readLines() reads in lines until the end of the file. Then the grepl counts lines beginning with l (adding 1) and the ones beginning with r (adding -1), then incrementing/decrementing as appropriate: the first non-empty line is not counted as it's the only code that is run.

Starts/ends with a newline for reversing and concatenation purposes.

Possibly some -> or <- chicanery will yield a shorter result -- indeed, Robin Ryder has proven me right, and it's shorter by a lot!

\$\endgroup\$
  • \$\begingroup\$ Very cool! I think you could save 2 bytes by using grepl("l<",l<-readLines()) and the equivalent for r. (And I've been working on the chicanery, but haven't got it to work yet!) \$\endgroup\$ – Robin Ryder Dec 16 '20 at 23:16
  • 1
    \$\begingroup\$ Yes! Really nice! I haven't figured-out how to get Robin's idea with the l< regex to avoid matching the regex itself, but this seems to be Ok for 90 bytes... \$\endgroup\$ – Dominic van Essen Dec 17 '20 at 0:04
  • \$\begingroup\$ @DominicvanEssen Ah, very nice. I think it's 91 since there needs a leading newline for a program that starts with a "reverse" and has some more concatenations. \$\endgroup\$ – Giuseppe Dec 17 '20 at 1:15
  • 1
    \$\begingroup\$ 26 bytes of chicanery. ;-) \$\endgroup\$ – Robin Ryder Dec 17 '20 at 8:41
4
\$\begingroup\$

Brain-Flak (Rain-Flak), 16 bytes

({}())#)])([}{(

Try it online!

Explanation

Making a program that when repeated counts up is easy

({}())

This adds 1 and with no input it defaults to zero, so repeating it counts the number of times.

However reversing is a little trickier. Only one balanced string is also a balanced string in reverse and that is the empty string, so we need to use some comments. We use the line comments of the Rain-Flak interpter and hide a payload between a # and a newline. Which simply is

({}[()])

This works the same way as the original program but with minus 1 instead of 1.

\$\endgroup\$
3
\$\begingroup\$

Haskell, 35 bytes

main=print$0--1- 
 +1--0$tnirp=niam

Try it online!

I tried for quite a bit to do this without comments. It doesn't seem impossible, but it does seem very hard.

\$\endgroup\$
3
\$\begingroup\$

Python 3, 109 bytes

Same approach as my zsh answer, but it actually beats the other Python answer!

c=open(__file__).read().count;print(c('wx')-c('y''z'))#))'zy'(c-)'x''w'(c(tnirp;tnuoc.)(daer.)__elif__(nepo=c

Try it online!

\$\endgroup\$
  • 1
    \$\begingroup\$ Reading the program's own code isn't usually allowed, is it? Or is that rule only for quines? \$\endgroup\$ – user253751 Dec 17 '20 at 18:38
  • \$\begingroup\$ @user253751 as far as I can see, that rule only applies for quines yes. \$\endgroup\$ – pxeger Dec 17 '20 at 20:19
2
\$\begingroup\$

Charcoal, 16 bytes

υΣI⁰⎚¹±υ⊞υ¹⎚⁰IΣυ

Try it online! Explanation:

υ

Print the list.

ΣI⁰

Cast 0 to string, then take the digital sum and print it (this happens to do nothing).

Clear the canvas.

¹

Print a -.

±υ

Print the negated list.

⊞υ¹

Push 1 to the list. (This is what actually affects the final output.)

Clear the canvas.

Print nothing.

IΣυ

Cast the sum of the list to string and print it. (This code at the end of the last copy is the only output that survives the program.)

Try it reversed! Explanation: The middle instructions differ slightly when the code is reversed:

¹

Print a -.

υ

Print the list.

⊞υ±¹

Push -1 to the list.

\$\endgroup\$
  • \$\begingroup\$ This looks really impressive \$\endgroup\$ – Redwolf Programs Dec 16 '20 at 23:48
2
\$\begingroup\$

Python 3, 164 bytes


import atexit as a;a._clear();a.register(lambda:print(v));v=locals().get('v',0)+1#;1-)0,'v'(teg.)(slacol=v;))v(tnirp:adbmal(retsiger.a;)(raelc_.a;a sa tixeta tropmi

Try it online! Or use this program builder (Input F for forward and R for reverse).

\$\endgroup\$
  • 1
    \$\begingroup\$ You can use vars instead of locals \$\endgroup\$ – pxeger Dec 17 '20 at 8:37
2
\$\begingroup\$

Zsh, 91 bytes

<<<$[`grep -c wx $0`-`grep -c y\z $0`];:<<'Q'
'Q'<<:;]`0$ zy c- perg`-`0$ x\w c- perg`[$<<<

Try it online!

Explanation

The overall idea is to read the source file and count the number of occurrences of the code forwards, minus the number backwards.

     `grep -c wx $0`                           # count occurrences of `wx`
                     `grep -c y\z $0`          # count occurrences of `yz`*
   $[               -                ]         # subtract
<<<                                            # print
                                      ;        # then
                                       :       # do nothing,
                                        <<'Q'  # with the rest of the file**

*: The backslash in the middle prevents the call to grep itself from being counted as an instance. In the mirrored copy on the next line, the backslash is placed inside wx instead, so that when re-reversed, it matches the negative one instead.

**: This starts a here-document, which consumes as input the rest of the file until the first line containing only FW. The single-quotes prevent execution of any $[...] and `...` parts from any possible repeated sections afterwards. We can't use line comments because grep -c outputs the number of matching lines, not individual matches. In another language we won't have this limitation.

The whole program is then duplicated, with the \ inside the wx instead of the yz, is then reversed and put on the next line, so that it works as expected when the first instance is a reversed one.

\$\endgroup\$
2
\$\begingroup\$

Klein 000, 12 bytes

\@+
 -
1
+@\

Try it online!

Reversed

\@+
1
- 
+@\

Try it online!

\$\endgroup\$
2
\$\begingroup\$

Wolfram Language (Mathematica REPL), 5 bytes

0+1-0

Test cases:

0+1-0            1
0+1-00+1-0       2
0-1+0           -1
0-1+00-1+0      -2
0+1-00-1+0       0
0+1-00-1+00-1+0 -1

Try it online!

\$\endgroup\$
  • \$\begingroup\$ This is a snippet, since Mathematica doesn't implicitly output (see comments on the question) \$\endgroup\$ – att Dec 17 '20 at 7:15
  • 1
    \$\begingroup\$ If you want to keep your answer like this you can switch to a language like bc that implicitly outputs the result. \$\endgroup\$ – ovs Dec 17 '20 at 10:14
  • \$\begingroup\$ See the When a REPL acceptable meta and similar. I shall edit to add that this is explicitly REPL, or is run from the command line, both which implicitly echo the final value. Mathematica "script" is not used as often from what I can tell, but is what people are expecting when you say Mathematica. \$\endgroup\$ – Imanton1 Dec 17 '20 at 16:07
2
\$\begingroup\$

JavaScript, 131 121 122 bytes

  • -10 thanks to Arnauld
  • +1 I forgot that the newline would also be reversed, so another one needed to be added

clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc;

(notice the leading and trailing newlines. the stacksnippets removes some of the leading and trailing newlines for the entire snippet, but it still works with/without the first and last newlines)

Try It Right Here! (TryItOnline has an error where clearTimeout is not defined, but clearTimeout is a valid JavaScript function.)

aB

clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

aBaB

clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc


clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

Ba

clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

BaBa

clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc


clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

aBBa

clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc


clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

aBBaBa

clearTimeout(this.a);a=setTimeout(console.log,0,b=-~this.b)//)b.siht-~=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc


clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc


clearTimeout(this.a);a=setTimeout(console.log,0,b=~-this.b)//)b.siht~-=b,0,gol.elosnoc(tuoemiTtes=a;)a.siht(tuoemiTraelc

\$\endgroup\$
  • 1
    \$\begingroup\$ That's a really ingenious use of the setTimeout and clearTimeout functions! \$\endgroup\$ – Redwolf Programs Dec 17 '20 at 7:58
  • 1
    \$\begingroup\$ You can save some bytes by using -~this.b and ~-this.b instead of (this.b||0)+1 and (this.b||0)-1 respectively. \$\endgroup\$ – Arnauld Dec 17 '20 at 8:11
  • \$\begingroup\$ Thanks @Arnauld, I always forget that ~undefined, ~NaN, ~null, etc. (anything that is relatively a 0) results in -1. \$\endgroup\$ – Samathingamajig Dec 17 '20 at 8:23
  • \$\begingroup\$ Also, since this is intended to be run in a browser, you could just use alert instead of console.log. (But because the popups are not very user-friendly, you may want to add alert = console.log in the code snippets.) \$\endgroup\$ – Arnauld Dec 17 '20 at 8:41
2
\$\begingroup\$

Python IDLE, 5 bytes

0-~+0

Try it online!

Explanation

Forwards

0      # zero
 -~    # minus-complement (the increment prefix "operator", which
       #                   also works as a binary add-plus-one)
   +0  # zero

Concatenated

0           # zero
 -~         # plus one plus
   +00      # zero
      -~    # plus one plus
        +0  # zero

Reversed

0      # zero
 +     # plus
  ~-   # complement-minus (the decrement prefix "operator")
    0  # zero

Bonus variants

  • 0-~-0, which counts up regardless of flipping (in fact, it's palindromic);
  • 0+~+0, which counts down regardless of flipping.
\$\endgroup\$
2
\$\begingroup\$

Python 3, 112 bytes


import os#1=-KO_R.so
os.system('cls')#)5-KO_R.so(tnirp
print(os.R_OK-3)#)'slc'(metsys.so
os.R_OK+=1#so tropmi

very ugly, but works.

\$\endgroup\$
  • 1
    \$\begingroup\$ Welcome to Code Golf! This is a nice first answer. I don't know how your program is supposed to work, so this link doesn't work currently, but I'd recommend editing that and adding it to your answer. TIO also automatically counts bytes and generates Markdown for your answer, which is nice. \$\endgroup\$ – user Dec 18 '20 at 23:34
2
\$\begingroup\$

ARM Thumb, 8 bytes excluding return statement

Raw machine code:

2101 1840 3901 2100

Assembly:

        .thumb
        @ R1 = 1
        movs    r1, #1
        @ r0 += 1
        adds    r0, r1
        @ Dummy code
        subs    r1, #1
        movs    r1, #0

Reverse each 16 bits

2100 3901 1840 2101
        .thumb
        @ r1 = 0
        movs    r1, #0
        @ r1 = -1
        subs    r1, #1
        @ r0 += -1
        adds    r0, r1
        @ Dummy code
        movs    r1, #1

Going forwards, it sets r1 to 1 and adds it to r0

Going backwards, it sets r1 to 0, subtracts 1 to get r1 to -1 (since Thumb can only load 0-255), then adds it to r0 effectively subtracting 1.

Call it with r0 = 0.

You need to end it with a return statement (bx lr or 4770 in hex) at the end, but those four instructions can be repeated forward and backwards as many times as you desire.

\$\endgroup\$
2
\$\begingroup\$

ARM (NOT thumb), 16 bytes excluding return instruction

Second, entirely different answer, still 4 instructions though.

Machine code:

01 10 80 e3 01 00 80 e0 e0 80 00 01 e3 f0 10 00

This one, unlike my Thumb submission, is entirely different in that it is byte reversible (hence why it is split in 8 bits instead of 32 bits)

It happens to do basically the same thing, though, add 1 on forwards and -1 on backwards.

Forwards:

        movs      r1, #1
        add       r0, r0, r1
        smlatteq  r0, r0, r0, r8
        andseq    pc, r0, r3, ror #1

Backwards:

        movs      r1, #-1   @ a.k.a. mvns      r1, #0
        add       r0, r0, r1
        smlatteq  r0, r0, r0, r8
        tsteq     r0, r3, ror #1

You may be asking yourself, "smlatteq? andseq? tsteq? What the **** do those do?"

The answer is nothing unless the zero flag is set.

This code heavily abuses ARM's conditional execution and "s" instructions.

movs will set the condition flags on the value it sets (why this exists for the immediate form, I will never know). I set them to 1 on forwards, and -1 on backwards. These are both non-zero, so they clear the zero flag.

We also use the version of add which does not update the flags, so the zero flag remains clear.

Therefore, since the zero flag is not set, all instructions with the eq suffix will be ignored.

And that is a VERY good thing, because ands pc, r0, r3, ror #1 would almost certainly crash the program (it would jump to a garbage address)

Therefore, in terms of what is effectively executed, it is this:

Forwards:

        movs      r1, #1
        add       r0, r0, r1
        nop
        nop

Backwards:

        movs      r1, #-1           @ a.k.a. mvns      r1, #0
        add       r0, r0, r1
        nop
        nop

Similar to my Thumb answer, you can repeat these as much as you wish, but you must put a bx lr (e12fff1e) at the end, and it is called with r0 == 0.

\$\endgroup\$
1
\$\begingroup\$

Ruby, 60 bytes

Note trailing newline:

a||=0;a+=1;at_exit{p a;exit!}#}!tixe;a p{tixe_ta;1=-a;0=||a

Try it online!

Reversed version (leading newline):


a||=0;a-=1;at_exit{p a;exit!}#}!tixe;a p{tixe_ta;1=+a;0=||a

Try it reversed!

at_exit specifies a block to be executed upon exit, SystemExit exception, or uncatchable error. exit! specifically bypasses these, giving the ability to skip all but the first registered block.

\$\endgroup\$
1
\$\begingroup\$

Wolfram Language (Mathematica), 31 bytes

tnirP//1-eniL$--
$Line++//Print

Try it:

A full program. $Line has an initial value of 1. In a notebook, it would increment for each input expression, but this doesn't apply outside the REPL.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.