173
\$\begingroup\$

A truth-machine (credits goes to this guy for coming up with it) is a very simple program designed to demonstrate the I/O and control flow of a language. Here's what a truth-machine does:

  • Gets a number (either 0 or 1) from STDIN.

  • If that number is 0, print out 0 and terminate.

  • If that number is 1, print out 1 forever.

Challenge

Write a truth-machine as described above in your language of choice. The truth-machine must be a full program that follows these rules:

  • take input from STDIN or an acceptable alternative
    • If your language cannot take input from STDIN, it may take input from a hardcoded variable or suitable equivalent in the program
  • must output to STDOUT or an acceptable alternative
    • If your language is incapable of outputting the characters 0 or 1, byte or unary I/O is acceptable.
  • when the input is 1, it must continually print 1s and only stop if the program is killed or runs out of memory
  • the output must only be either a 0 followed by either one or no newline or space, or infinite 1s with each 1 followed by either one or no newline or space. No other output can be generated, except constant output of your language's interpreter that cannot be suppressed (such as a greeting, ANSI color codes or indentation). Your usage of newlines or spaces must be consistent: for example, if you choose to output 1 with a newline after it all 1s must have a newline after them.

  • if and only if your language cannot possibly terminate on an input of 0 it is acceptable for the code to enter an infinite loop in which nothing is outputted.

Since this is a catalog, languages created after this challenge are allowed to compete. Note that there must be an interpreter so the submission can be tested. It is allowed (and even encouraged) to write this interpreter yourself for a previously unimplemented language. Other than that, all the standard rules of must be obeyed. Submissions in most languages will be scored in bytes in an appropriate preexisting encoding (usually UTF-8).

Catalog

The Stack Snippet at the bottom of this post generates the catalog from the answers a) as a list of shortest solution per language and b) as an overall leaderboard.

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

## Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

## Ruby, <s>104</s> <s>101</s> 96 bytes

If there you want to include multiple numbers in your header (e.g. because your score is the sum of two files or you want to list interpreter flag penalties separately), make sure that the actual score is the last number in the header:

## Perl, 43 + 2 (-p flag) = 45 bytes

You can also make the language name a link which will then show up in the snippet:

## [><>](http://esolangs.org/wiki/Fish), 121 bytes

<style>body { text-align: left !important} #answer-list { padding: 10px; width: 290px; float: left; } #language-list { padding: 10px; width: 320px; float: left; } table thead { font-weight: bold; } table td { padding: 5px; }</style><script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="language-list"> <h2>Shortest Solution by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr> </thead> <tbody id="languages"> </tbody> </table> </div> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr> </thead> <tbody id="answers"> </tbody> </table> </div> <table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr> </tbody> </table><script>var QUESTION_ID = 62732; var ANSWER_FILTER = "!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe"; var COMMENT_FILTER = "!)Q2B_A2kjfAiU78X(md6BoYk"; var OVERRIDE_USER = 12012; var answers = [], answers_hash, answer_ids, answer_page = 1, more_answers = true, comment_page; function answersUrl(index) { return "https://api.stackexchange.com/2.2/questions/" + QUESTION_ID + "/answers?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + ANSWER_FILTER; } function commentUrl(index, answers) { return "https://api.stackexchange.com/2.2/answers/" + answers.join(';') + "/comments?page=" + index + "&pagesize=100&order=desc&sort=creation&site=codegolf&filter=" + COMMENT_FILTER; } function getAnswers() { jQuery.ajax({ url: answersUrl(answer_page++), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { answers.push.apply(answers, data.items); answers_hash = []; answer_ids = []; data.items.forEach(function(a) { a.comments = []; var id = +a.share_link.match(/\d+/); answer_ids.push(id); answers_hash[id] = a; }); if (!data.has_more) more_answers = false; comment_page = 1; getComments(); } }); } function getComments() { jQuery.ajax({ url: commentUrl(comment_page++, answer_ids), method: "get", dataType: "jsonp", crossDomain: true, success: function (data) { data.items.forEach(function(c) { if (c.owner.user_id === OVERRIDE_USER) answers_hash[c.post_id].comments.push(c); }); if (data.has_more) getComments(); else if (more_answers) getAnswers(); else process(); } }); } getAnswers(); var SCORE_REG = /<h\d>\s*([^\n,<]*(?:<(?:[^\n>]*>[^\n<]*<\/[^\n>]*>)[^\n,<]*)*),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/; var OVERRIDE_REG = /^Override\s*header:\s*/i; function getAuthorName(a) { return a.owner.display_name; } function process() { var valid = []; answers.forEach(function(a) { var body = a.body; a.comments.forEach(function(c) { if(OVERRIDE_REG.test(c.body)) body = '<h1>' + c.body.replace(OVERRIDE_REG, '') + '</h1>'; }); var match = body.match(SCORE_REG); if (match) valid.push({ user: getAuthorName(a), size: +match[2], language: match[1], link: a.share_link, }); else console.log(body); }); valid.sort(function (a, b) { var aB = a.size, bB = b.size; return aB - bB }); var languages = {}; var place = 1; var lastSize = null; var lastPlace = 1; valid.forEach(function (a) { if (a.size != lastSize) lastPlace = place; lastSize = a.size; ++place; var answer = jQuery("#answer-template").html(); answer = answer.replace("{{PLACE}}", lastPlace + ".") .replace("{{NAME}}", a.user) .replace("{{LANGUAGE}}", a.language) .replace("{{SIZE}}", a.size) .replace("{{LINK}}", a.link); answer = jQuery(answer); jQuery("#answers").append(answer); var lang = a.language; lang = jQuery('<a>'+lang+'</a>').text(); languages[lang] = languages[lang] || {lang: a.language, lang_raw: lang.toLowerCase(), user: a.user, size: a.size, link: a.link}; }); var langs = []; for (var lang in languages) if (languages.hasOwnProperty(lang)) langs.push(languages[lang]); langs.sort(function (a, b) { if (a.lang_raw > b.lang_raw) return 1; if (a.lang_raw < b.lang_raw) return -1; return 0; }); for (var i = 0; i < langs.length; ++i) { var language = jQuery("#language-template").html(); var lang = langs[i]; language = language.replace("{{LANGUAGE}}", lang.lang) .replace("{{NAME}}", lang.user) .replace("{{SIZE}}", lang.size) .replace("{{LINK}}", lang.link); language = jQuery(language); jQuery("#languages").append(language); } }</script>

\$\endgroup\$
19
  • 3
    \$\begingroup\$ Assuming any behaviour is fine for all invalid inputs? \$\endgroup\$
    – Cruncher
    Commented Nov 3, 2015 at 17:33
  • 3
    \$\begingroup\$ @Cruncher Yes, the only inputs you should expect to get are 0 and 1. \$\endgroup\$ Commented Nov 3, 2015 at 17:38
  • 5
    \$\begingroup\$ Catalog is borked. \$\endgroup\$ Commented Nov 6, 2015 at 15:18
  • 2
    \$\begingroup\$ Catalog appears to consider Bf and bf to be different languages. \$\endgroup\$ Commented Nov 10, 2015 at 1:13
  • 1
    \$\begingroup\$ Is one allowed to print an infinite number of 1s? That is, not print out 1s forever, but print out an infinite list of 1s all at once? This would be theoretically demonstrated, but the language has no notion of printing more than once. It just generates an output. So is it okay if it runs indefinitely, but would print infinite 1s given infinite time (to finish executing)? \$\endgroup\$
    – AviFS
    Commented Apr 26, 2020 at 1:42

495 Answers 495

1 2
3
4 5
17
4
\$\begingroup\$

PowerShell, 24 Bytes

param($a)do{$a}while($a)

Gets variable $a, then uses the do-while loop functionality to output $a at least once, but continuing the loop if $a is truthy (i.e., 1).


Alternatively, using traditional while looping, also 24 bytes

param($a)while($a){$a}$a

In this instance, if $a is falsey, the while loop will never be executed and just the value of $a will be printed in the end statement. If $a is truthy, the program will enter the while loop and continuously print the value of $a.

\$\endgroup\$
4
\$\begingroup\$

Befunge-98, 16 bytes

&>:;#,1';#<_'0,@

Tested in pyfunge and BeQunge.

Simpler two-line version

&>:! |
@^,1']'0,

I like the previous one more, but this is what I came up with first.

\$\endgroup\$
6
  • \$\begingroup\$ I'm not 100% sure on my Befunge skills, but &:.jq>:.< appears to work, and is 9 bytes. \$\endgroup\$
    – user45941
    Commented Nov 3, 2015 at 19:07
  • \$\begingroup\$ @Mego Damn. :-P \$\endgroup\$ Commented Nov 3, 2015 at 19:08
  • \$\begingroup\$ Whoops, looks like I missed a char. &::.jq>:.< for 10. \$\endgroup\$
    – user45941
    Commented Nov 3, 2015 at 19:11
  • \$\begingroup\$ As @ThomasKwa pointed out in chat, &::.jq# works and is 7. \$\endgroup\$
    – user45941
    Commented Nov 6, 2015 at 19:04
  • \$\begingroup\$ @Mego I'm not going to steal that. I'll let the inventor(s) post it. \$\endgroup\$ Commented Nov 6, 2015 at 19:08
4
\$\begingroup\$

Prolog, 28 bytes

a(X):-write(X),X=0,!;a(X).

The cut ! is necessary to terminate the execution in the interpreter, otherwise it will wait to see if the user wants to get other answers.

\$\endgroup\$
2
  • 2
    \$\begingroup\$ No need for the extra parentheses! Saves 2 bytes. \$\endgroup\$
    – mat
    Commented Jan 4, 2016 at 13:41
  • 1
    \$\begingroup\$ @mat true. Not sure what I was thinking! \$\endgroup\$
    – Fatalize
    Commented Jan 4, 2016 at 13:41
4
\$\begingroup\$

Turing Machine Code, 19 bytes

0 0 * * 1
0 * 1 r 0

Halts on 0 because there is no state 1.

\$\endgroup\$
4
\$\begingroup\$

Shakespeare Programming Language, 189 bytes

.
Ajax,.
Ford,.
Act I:.
Scene I:.
[Enter Ajax and Ford]
Ford:
Listen to thy heart.
Scene II:.
Ford:
Open thy heart.Is cat as big as you?If so, let us return to scene II.
[Exeunt]

Ungolfed:

The Construction of a Truth-Machine in Denmark.

Hamlet, the input.
Ophelia, who orders him around.

Act I: A truth-machine.

Scene I: In which Hamlet learns that all he needs, he can find in his heart.

[Enter Hamlet and Ophelia]

Ophelia:
  Listen to thy heart.

Scene II: In which Ophelia proclaims her doubts about Hamlet.

Ophelia:
  Open thy heart. Is my lover as fair as thee?
  If so, let us return to scene II.

[Exeunt]

I'm using drsam94's SPL compiler + GCC to compile this.

To test:

$ python splc.py tm.spl > tm.c
$ gcc tm.c -o tm.exe
$ echo 0 | ./tm
0
$ echo 1 | ./tm
1111111111111111111111111111111111111111111111...
\$\endgroup\$
2
  • \$\begingroup\$ Do you have the link for the Python implementation of SPL? looking to work on a JavaScript fork of it... \$\endgroup\$ Commented Aug 30, 2016 at 23:03
  • \$\begingroup\$ @WallyWest Here it is! \$\endgroup\$
    – Copper
    Commented Aug 30, 2016 at 23:07
4
\$\begingroup\$

Japt, 4 bytes

ÿ ©ß

As of 25 Oct 2016, I have implemented the recursion feature ß, which calls the entire program as a function. This is used here like so:

      // Implicit: U = input integer
ÿ     // Since there's no value to work on, use U here. Alert U and return it.
  ©   // If U is truthy (1),
   ß  //   run the program again with the same inputs.

Test it online!

\$\endgroup\$
6
  • 1
    \$\begingroup\$ Yay! We should hold competitions between Japt, 𝔼𝕊𝕄𝕚𝕟, and Teascript to see which is the most effective JS-based lang. \$\endgroup\$ Commented Nov 4, 2015 at 3:10
  • \$\begingroup\$ @ןnɟuɐɯɹɐןoɯ That sounds great! But let's have at least another week to develop the langs; I've only worked on the Japt interpreter for ~8 hours and gotten ~2/3 of the features (all the easy ones) done. :-) \$\endgroup\$ Commented Nov 4, 2015 at 3:13
  • \$\begingroup\$ Sure! I could probably implement some improvements, too. \$\endgroup\$ Commented Nov 4, 2015 at 3:52
  • \$\begingroup\$ Just curious, is there a shorter way to do this in newer Japt versions? \$\endgroup\$
    – FlipTack
    Commented Dec 22, 2016 at 13:24
  • 1
    \$\begingroup\$ @Flp.Tkc Actually, it can be Uÿ ©ß because ß implicitly uses the inputs as arguments. Thanks ;-) \$\endgroup\$ Commented Dec 22, 2016 at 14:05
4
\$\begingroup\$

HP48's RPL, 22.5 bytes

« WHILE DUP REPEAT DUP END »

Since there is no such thing as STDIN or STDOUT on the HP48, the input is taken on the stack, and one "0" or an infinity of "1"s are pushed back on the stack.

If you try it, you will have to kill the program in order to see the "1"s since the stack is not refreshed while the program is running (Just press the "ON" button).

PS: The HP48's memory is made of 4 bits words, hence the non-integer bytes size

\$\endgroup\$
4
\$\begingroup\$

PUBERTY, 369 bytes

It is May 1, 2018, 3:01:04 PM.Y is in his bed, bored.His secret kink is J.Soon the following sounds become audible.oh yeah yeah yeah hrg fap yeah yeah yeah fap yeah fap yeah yeah mmf yeah yeah yeah hrg yeah hrg fap yeah yeah yeah yeah fap yeah fap yeah mmf yeah yeah yeah yeah yeah yes yeah yeah yeah yeah yeah hrg fap yeah fap yeah fap yeah yeah yeah yeah mmf yeah mmf

Ungolfed

It is May 1, 2018, 3:01:04 PM.
Yhprum is in his bed, bored.
His secret kink is humaninteraction.
Soon the following sounds become audible.

oh yeah yeah yeah
hrg
    fap yeah yeah yeah fap yeah fap yeah yeah
mmf

yeah yeah yeah

hrg
    yeah
    hrg
       fap yeah yeah yeah yeah fap yeah fap yeah
    mmf
    yeah yeah yeah yeah yeah

    yes

    yeah yeah yeah yeah yeah
    hrg
        fap yeah fap yeah fap yeah yeah yeah yeah
    mmf
    yeah
mmf

This was very much harder than I expected it to be using this language.

Explanation

PUBERTY is a wonderful language. It has 6 registers (A, B, C, D, E, F) and one register pointer, all initialized to 0. At the end of each instruction, REGPTR %= 6 and REG[REGPTR] %= 256.

These are the commands used in this program:

  • oh reads an ASCII character and stores its value into the current register
  • yeah increments REGPTR by 1
  • hrg...mmf loops until the current register has a value of zero
  • fap increments the current register by 1
  • yes prints the ASCII char corresponding to the value of the current register

The program starts with the header - the first four lines

It is May 1, 2018, 3:01:04 PM.

This sets $D to the Unix timestamp of the date % 256. In this case, we set it to 48. This statement is required

Yhprum is in his bed, bored.

This initializes $C to 6, the number of chars in the name, but we don't use this at all. This statement is required.

His secret kink is humaninteraction.

This line is where you declare all your kinks, if you want to learn about what they do, check out the esolang page since we don't use them here. This statement is required.

Soon the following sounds become audible.

Required line, does nothing.

oh yeah yeah yeah
hrg
    fap yeah yeah yeah fap yeah fap yeah yeah
mmf

yeah yeah yeah

read in a 0 or 1, then loop until $D is zero while incrementing $A and $B. This leaves us with $A containing ASCII value 0 or 1, depending on what was inputted and $B containing 208. Then move REGPTR back to A

hrg
    yeah
    hrg
       fap yeah yeah yeah yeah fap yeah fap yeah
    mmf
    yeah yeah yeah yeah yeah

    yes

In the inner loop, move REGPTR to $B (which has the value 208) and loop until it is zero while incrementing $A and $F. This leaves us with $A containing 48 or 49 (the ASCII codes for 0 or 1) and F containing 48. Then print $A, which will output a 0 or 1 depending on which one was inputted.

    yeah yeah yeah yeah yeah
    hrg
        fap yeah fap yeah fap yeah yeah yeah yeah
    mmf
    yeah
mmf

Now we move REGPTR to $F and loop until that is zero while incrementing $A and $B. This leaves us with $A containing the ASCII value 0 or 1 and $B containing 208, just like it had at the start of the loop. The loop then exits if $A == 0 or loops infinitely if $A == 1.

This is my first codegolf answer so excuse any mistakes I made pls.

\$\endgroup\$
4
\$\begingroup\$

PowerShell, 16 15 bytes

for(;$args){1}0

Try it Online!

Edit:
-1 byte thanks to @AdmBorkBork

\$\endgroup\$
1
  • \$\begingroup\$ Use a for loop to save a byte Try it online! \$\endgroup\$ Commented Jul 19, 2018 at 15:45
4
\$\begingroup\$

brainfuck (portable), 29 28 bytes

>>>,.[[->+<<+>]>-]<+[<<]>[.]

Try it online!

(Improved by 1 byte thanks to Jo King, who found a terser way to start the [<<] loop.)

I know that on PPCG it's normally sufficient for an answer to work on one interpreter, but as this is a catalogue, I wanted a demonstration of a brainfuck answer that should work on any interpreter, and which exits without error on input 0. This program makes no assumptions about cell size, EOF behaviour, wrapping, tape extension to the left, etc. It's the shortest brainfuck truth-machine I'm aware of with these properties.

Explanation

>>>,.[[->+<<+>]>-]<+[<<]>[.]
>>>,                            Input a character to the fourth cell
    .                           Output that character
     [           ]              While the current cell is nonzero:
      [->+<<+>]                   Move the value to the next and previous cells
               >                  Make the next cell current
                -                 and decrement it
                  <+            Starting behind the current cell, at value 1
                    [<<]        Move back two cells at a time until we find zero
                        >[ ]    If the cell to the right is nonzero:
                          .       Output it forever

The basic idea here is to create a range on the tape, containing all values from the input's ASCII code down to 0. (So for example, if the input is 0, we get 48 in the third cell, 47 in the fourth cell, 46 in the fifth cell, etc..) Once we've done that, we look at alternate values of the range until we end up at a tape element before the start of the range. If the range has an even length (i.e. the input has an even ASCII code), we'll end up two cells to the left of it, so moving to the right we'll end up in a cell we've never written to (and thus still has the value zero). If the range has an odd length, we'll end up only one cell to its left, so >[.] will move to the first cell of the range (i.e. the user input) and output it in a loop forever.

\$\endgroup\$
0
4
\$\begingroup\$

Deoxyribose, 18 bytes

Updated for the new v3 spec

ATGGAGAAGAGCATAAAT

Explanation:

ATG                         ATA (*)
GAG Glu     Dupe            TGG Trp     Power
AAG Lys     Pop             AGA Arg     Unipop
AGC Ser     Jump if <= 0    AGA Arg     Unipop
ATA *                       GCA Ala     Modulo
AAT Asn     Loop            TAA End
  • Execution starts at the initial ATG.
  • The top element of the main stack is duplicated & printed, then If the value is less than or equal to zero, jump to the ATA formed by the Asn and the start codon (remember, the code is circular), then run through a series of no-ops, including printing some non-printable characters. If the value is greater than 0, loop back to the start.

If you don't like the ugly sequence of no-ops, adding ATG to the end to make the loop target explicit results in a clean termination immediately after the jump, for three more bytes.


Deoxyribose 2, 21 bytes

ATGTGAGAAAAATCTAACTTA

Explanation:

ATG Start                           TAA Stop ┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┐
TGA Block size = 56               ┏ TGT Cys     Destination of Asn ┆
GAA Glu     Duplicate             ┃ GAG Glu     Duplicate          ┆
AAA Lys     Pop as int            ┃ AAA Lys     Pop as int         ┆
TCT Ser     If >= 0, jump to Thr ┐┞ AAT Asn     Jump back to Cys   ┆
AAC Asn     Jump back to Cys ────┼┘                                ┆
TTA                              └─ ACT Thr     Destination of Ser ┆
                                     └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘

This is the first challenge on this site ever answered in this language (since it's only a week old), but I think it's a good showcase of what the language can do so I'll provide a bit of an explanation of what's going on. If you happen to be really interested, the spec, a Python-based interpreter, and additional (less golfed) examples are on GitHub.

Deoxyribose is a stack-based language with a small instruction set and a syntax based on DNA. Execution takes place on a circular stretch of DNA, translating 3-digit "codons" into proteins, each of which corresponds to either

  • an operation on one or both of the stacks, or
  • a (perhaps conditional) jump to a particular sequence elsewhere in the code.

These jumps can lead to frameshifts, where the read head is moved a non-integer number of codons and the same bit of code ends up doing two totally different things at different times. The degenerate nature of the genetic code makes it possible (and fun!) to use this to your advantage.

\$\endgroup\$
1
  • \$\begingroup\$ I love this language concept! \$\endgroup\$
    – histocrat
    Commented May 2, 2018 at 21:45
4
\$\begingroup\$

W s, 1 byte

The s flag forces a read from STDIN. This flag can be appended to the end of the command-line.

w

No, I didn't just make a built-in for the question.

Here is the expanded program (because w requires two inputs)

aaw

This decodes into:

mywhile(a[0],'a[0]',a)

Which means:

while a[0]:
    print(a[0])

The print is implicit in every while iteration. Since a[0] is always 1 once it is defined as 1, this will print 1 forever (the body is the same as the condition).

So you might say that this prints nothing if the input is 0. You are wrong, the w instruction returns the condition 0 after the while statement is done. Therefore it gets returned and gets outputted.

W s, 4 bytes

W was designed to be very powerful so that while loops are unneccecary. This program avoids this at the cost of being significantly longer. (Please don't use the while loop (which is simply for presentation purposes) in your W programs. Thank you.)

ibE&

Explanation

   & % Perform logical AND between the input and the code block.
     % If the input is 1, execute the following code block:
i E  %     Count to infinity,
 b   %     Printing the input in every iteration
     % Otherwise (part of the AND logic):
     %     Return 0, exit the program.
\$\endgroup\$
4
\$\begingroup\$

Shakespeare Programming Language, 123 120 bytes

(Whitespace added for readability)

T.Ajax,.Puck,.Act I:.Scene I:.[Exeunt][Enter Ajax and Puck]
Ajax:Listen tothy.Open heart.
     Am I worse you?If solet usAct I.

Try it online!

I make use of a trick to reuse Scene I. For some reason, it doesn’t error to keep taking input, so I do that. Then I just compare the input to zero, and loop if it’s greater. Saved 3 bytes by comparing to I instead of zero because characters initialize to zero—thanks Robin Ryder!

\$\endgroup\$
2
  • \$\begingroup\$ You can use Is I worse you? instead of Is zero worse you?, since all characters are implicitly initialized at 0. \$\endgroup\$ Commented Jan 21, 2020 at 14:59
  • \$\begingroup\$ True true, thank you! \$\endgroup\$ Commented Jan 22, 2020 at 15:03
4
\$\begingroup\$

Red, 28 bytes

func[a][until[prin a a = 0]]

Try it online!

Makes use of the fact that until will always execute its block at least once. The loop will only terminate if the argument passed to the function is 0, otherwise it will keep printing forever.

\$\endgroup\$
2
  • \$\begingroup\$ The loop will also terminate if you pass 0.0, 0%, $0, #"^(null)", 0:0, because it relies on the lax comparison. There's also ask for taking input from STDIN. \$\endgroup\$
    – 9214
    Commented Jun 1, 2021 at 17:00
  • 1
    \$\begingroup\$ is there a consensus on how red/rebol function submissions should be made? this answer only seems to have the body. \$\endgroup\$
    – Razetime
    Commented Jun 5, 2021 at 4:59
4
\$\begingroup\$

Flipbit, 10 bytes

?>>>>>.[.]

Try it online!

\$\endgroup\$
4
\$\begingroup\$

Python 3, 35 34 bytes

def l(i):
 if i:print(i);l(int(i))

Older python 3.8 only code

i=input()
while i:print(i:=int(i))

Try me!

Explination:

While this ties the best python 3 answer thanks xnor for saving me a byte

This uses a few interesting properties to achieve what it does:

  1. The input received is always a string when from a user input, thus the while-loop will start regardless if its a 1 or 0

  2. Inside the loop, we print the number for the first time, and simultaneously using the walrus operator which was introduced in python 3.8, we assign the integer value to i. Using recursion, this code can now work in all versions of python 3, while it isn't a major improvement in bytes count, I'd still count making the code work in more versions an improvement!

  3. Now, the value, if zero, is now converted from "0" to 0, meaning the loop will exit, otherwise if its 1, it keeps going!

I have tried hard to get lambdas to work, but every attempt ended up with more lines due to having to use recursion, if anyone has any ideas I am all ears! Meanwhile I will try to keep pushing this, the new version feels like it has more that can be pushed

\$\endgroup\$
2
  • 2
    \$\begingroup\$ Cute trick with the int. You can write while i: without parens saving a byte. \$\endgroup\$
    – xnor
    Commented Oct 28, 2021 at 11:22
  • \$\begingroup\$ Dang, Thanks, One less byte means we are no longer tying haha \$\endgroup\$ Commented Oct 28, 2021 at 11:23
4
\$\begingroup\$

Hello Hell, 34 bytes

[+^-/>]!*/*/>[+^>][+-/<]-/<[{*+}/]

Try it Online!

The first program in my new language - Hello Hell! For information on the commands, memory model, etc. check out the repo.

Explanation:

[+^-/>]                             # Set the first 6 cells to 0
       !                            # Input
        */*/                        # Set the cell to 0 or 49 depending on input
            >[+^>]                  # Move to the 13th cell
                  [+-/<]-/<         # Set cells 8-13 to 0
                           [{*+} ]  # If 1, loop forever,
                                /   #  otherwise print 0
\$\endgroup\$
1
  • \$\begingroup\$ okay good I just wanted the upvoting to happen not the explaining thank you very cool \$\endgroup\$
    – lyxal
    Commented Oct 28, 2021 at 12:48
4
\$\begingroup\$

Pure CPython 3.10 bytecode, 6 bytes

"Pure" means no constants and no names are allowed. As a result, the only method of input is by starting with values on the stack.

...and Python bytecode's only way to jump backwards (and therefore the only way to loop) uses "absolute" addressing, so my code assumes it is placed starting at instruction offset 3 (byte offset 6).

Hex of code: 04 00 46 00 70 03

Disassembly of code:

    >>    6 DUP_TOP
          8 PRINT_EXPR
         10 JUMP_IF_TRUE_OR_POP      3 (to 6)

Takes an integer on the stack. The easiest way to put 0 or 1 on the stack is:

          0 LOAD_ASSERTION_ERROR
          2 BUILD_TUPLE              X
          4 GET_LEN

Change X to 0 or 1. In hex, this is 4a 00 66 00 1e 00 (for 1) or 4a 00 66 01 1e 00 (for 0).

This will crash the interpreter for an input of 0 due to a buffer overflow. If this is not acceptable, add 2 bytes (append 53 00 (RETURN_VALUE)).

Attempt This Online! (0)

Attempt This Online! (1)


I'm going to use this opportunity to explain how CPython bytecode works. It's just an array of bytes, which are in opcode, oparg pairs.

For example, (hex) 01 02 03 04 is instruction_01(arg=02); instruction_03(arg=04).

The list of instructions is given in the documentation for the standard library dis module, although you sometimes need to dig about in Python's ceval.c to see exactly how they work.

In Python, bytecode is contained in a code object, which carries some metadata like source file lines, but the most important things are an array of constants (co_consts) and an array of names (co_names). In order to load a literal value, it must be loaded from co_consts; in order to lookup a global variable, its name must be in co_names. When I said I'm using "pure" bytecode, I mean that these arrays are both empty - so I can't use any literals (integers, strings, tuples, etc.), and I can't use any global variables, builtins, imports, or even look up any attributes. This allows an extremely minimal wrapper script (see the ATO link).

This leaves me with only PRINT_EXPR for output (or leaving a value on the stack), and no input at all other than taking a value already on the stack.

The truth machine is actually the easy part of this code, to be honest: it's essentially do { print x } while (x).

Loading an integer is a bit more involved: first I use LOAD_ASSERTION_ERROR to put a value on the stack. What value it is doesn't particularly matter, but this is one of only a few instructions I'm aware of that can load an object without any consts.

Then I use BUILD_TUPLE(1) to make the tuple (AssertionError,), and take its length with GET_LEN which is 1. To load 0 is a bit simpler: you only need

          0 BUILD_TUPLE              0
          2 GET_LEN

Although you can perfectly well leave the LOAD_ASSERTION_ERROR before that, to conveniently switch between loading 0 and 1.


Sidenote

GET_LEN is new in Python 3.10, so a historic method would have had to involve boolean <-> integer conversion, which is a bit more interesting IMO:

          0 LOAD_ASSERTION_ERROR
          2 DUP_TOP
          4 IS_OP                    0
          6 DUP_TOP
          8 BINARY_MULTIPLY
         10 PRINT_EXPR

This performs AssertionError is AssertionError, which is True. Then it does True * True to get the integer 1.

IS_OP(0) can be replaced with IS_OP(1) to do AssertionError is not AssertionError, which gives False, which gives 0.

\$\endgroup\$
4
\$\begingroup\$

Desmos, 51 50 45 bytes

o→\left\{i=0:[0],join(1,o!)\right\}
i=0
o=0

Try It Online! (Click the play button on the ticker up top (metronome icon) to run the program)

Desmos doesn't exactly have standard I/O support, but this should get the point across. Input is the i variable, output is the o variable. Each line is a separate expression, and the first expression needs to be in the ticker, as shown in the TIO.

Addendum: at the very least, this output method is accepted by default. Not sure about the input.

EDIT: a surprising -1, apparently parses properly as an action! Unfortunately, it still costs 3 bytes, which is the same as \to, BUT it allows me to change \to join to →join since the parser gets confused by \tojoin

EDIT: -5 thanks to zygan on discord who showed me that an action itself can be piecewise, and also me realizing that o! is shorter than o^o and doesn't even have to rely on wacky edge case behavior lol

\$\endgroup\$
7
  • 1
    \$\begingroup\$ 44 bytes \$\endgroup\$
    – Aiden Chow
    Commented Dec 22, 2021 at 3:40
  • \$\begingroup\$ Actually, even better: 39 bytes \$\endgroup\$
    – Aiden Chow
    Commented Dec 22, 2021 at 3:55
  • 1
    \$\begingroup\$ Oh oops, didn't notice that. In that case, change o.length to length(o) for 40 bytes. \$\endgroup\$
    – Aiden Chow
    Commented Dec 22, 2021 at 4:55
  • 1
    \$\begingroup\$ 33 bytes. I think this is about as low as it can get, unless I'm missing something. \$\endgroup\$
    – Aiden Chow
    Commented Dec 22, 2021 at 23:51
  • 1
    \$\begingroup\$ Will do, I have posted my own answer. \$\endgroup\$
    – Aiden Chow
    Commented Dec 23, 2021 at 19:59
4
\$\begingroup\$

Trilangle, 13 bytes

?!<(@^\<.#^)/

Try it on the online interpreter!

Unfolds to this:

    ?
   ! <
  ( @ ^
 \ < . #
^ ) / . .

As in every Trilangle program, control flow starts at the north corner heading southwest. \|/_ reflect control flow, while <^7>vL change the direction conditionally (depending on both the stored value and the direction of the IP).

The IP starts on the red path, where it encounters the following instructions:

  • ?: Read an integer from STDIN
  • !: Write an integer to STDOUT (with trailing newline)
  • (: Decrement
  • \: Redirect control flow
  • <: Branch

Upon reaching the branch instruction, the number inputted will already have been outputted once, and the stored value will be one less than that: -1 if the input is 0, or 0 if the input is 1. The branch instruction proceeds left for negative values and right otherwise.

If the value inputted was 0, the program follows the green path, which immediately hits @ (end program). Otherwise, it follows the blue path:

  • /: Redirect control flow

  • ): Increment, to cancel out the decrement instruction from earlier

  • ^: Redirect control flow

    (Walk off the edge of the board, and wrap around to the southeast corner)

  • .: No-op

  • #: Skip the next instruction

After encountering #, the IP jumps into the middle of the yellow loop. ! prints out the stored value (1) repeatedly, and the other two characters keep it in the loop.

<^ is not the only combination of control flow manipulators that works. I've found that at least the following pairs also work: <7, <v, <<, L>, ^>, >>. Interestingly, <\ causes it to print every odd number twice (1, 1, 3, 3, 5, 5, ...). All other pairs I've tried exhibit one of three behaviors:

  • Loop without hitting ! (e.g. L<)
  • Exit early, printing out finitely many numbers (e.g. <_)
  • Print a couple 1's before going back to the start and waiting for more input (e.g. <|)
\$\endgroup\$
3
\$\begingroup\$

AppleScript, 93 Bytes

...this verbosity astounds me.

set a to(display dialog""default answer"")'s text returned
repeat while a="1"
log 1
end
log 0
\$\endgroup\$
3
\$\begingroup\$

Haskell, 38 35 bytes

main=interact x
x"1"=cycle"1"
x a=a

The input must not be terminated by a newline. This works for me: echo -n 1 | ./truth-machine.

Edit: thanks @Zgarb for 3 bytes.

\$\endgroup\$
2
  • \$\begingroup\$ One-liner (also 35 byte): main=interact(\x->[1,read x..1]>>x) \$\endgroup\$
    – Laikoni
    Commented Feb 28, 2018 at 11:55
  • \$\begingroup\$ main=interact(\[c]->[c,'1'..c]) is 31 bytes. \$\endgroup\$
    – lynn
    Commented Sep 30, 2020 at 23:24
3
\$\begingroup\$

CJam, 8 bytes

q~{_o}h;

There's no point in linking to the online interpreter, because that one doesn't like infinite loops.

This one works as well, printing newlines:

q~{_p}h;

Explanation

q~   e# Read and evaluate input.
{    e# While the top of the stack is truthy (i.e. 1.).
  _o e# Print a copy of the value on the stack.
}h
;    e# We only get here if the value was 0. If so, discard the other 0 on the stack.
\$\endgroup\$
3
\$\begingroup\$

TI-BASIC, 8 bytes

There are two programs that achieve 8 bytes:

Repeat not(Ans
Disp Ans
End

Repeat is TI-BASIC's do-until loop, so it doesn't check the condition the first time. The other way is recursion (name the program prgmT):

Disp Ans
If Ans
prgmT

Both take input from Ans; call using 0:prgmT or 1:prgmT.

\$\endgroup\$
1
  • \$\begingroup\$ TIL the TI-84 doesn't have tail-call optimization for recursive programs. :( \$\endgroup\$
    – Jakob
    Commented May 25, 2018 at 21:30
3
\$\begingroup\$

Minkolang, 7 bytes

nd$,N?.

Try it here. (DON'T click Run!)

Explanation

n     Take integer from input
d     Duplicate
$,    0 if 0, 1 otherwise
N     Output as integer
?.    Halt if 0, continue otherwise

This works because n pushes -1 if the input is empty...which is truthy! Also, Minkolang is toroidal so when the program counter moves off the right edge, it wraps around to the left edge and continues.

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

Mouse, 16 bytes

?0=[0!$](1^1!)$

Ungolfed:

? 0 = [           ~ Read a number from STDIN and test it for equality with 0
  0 ! $           ~ If equal, print 0 and exit
]
( 1 ^             ~ While true,
  1 !             ~ Print 1
)$                ~ End of program
\$\endgroup\$
3
\$\begingroup\$

PoGo, 10 bytes

ifpouftogo

Explanation:

  • if - accept numerical input and place the result into the current memory cell
  • po - add current position in code to the top of the po stack
  • uf - output the value in the current memory cell as a number
  • to - execute the following command only if the value in the current memory cell is >0
  • go - pop the most recent po location off the stack and jump there

The "po" stack is a call stack used for flow control.

The program in pseudo code:

read int x
do:
    print x
while x > 0
\$\endgroup\$
3
\$\begingroup\$

Labyrinth, 6 bytes

?|:!:/

In the case of a 0 input, this terminates with an error. For a beautiful solution which exits cleanly, see Sp3000's answer.

Since the code is linear, the instruction pointer will move back and forth on the code (it will turn around when hitting a dead end, executing the instruction at the end only once). So what is happening?

?  Read the input as an integer.
|  Compute the bitwise OR of the top two stack elements (there is an infinite supply of
   zeroes at the bottom). This is a no-op at this point.
:  Duplicate the input.
!  Print it as an integer.
:  Duplicate the input.
/  Divide the input by itself. If the input was 0, the interpreter will throw an error,
   polluting STDERR, but we can ignore that. STDOUT remains unchanged. If the input was
   1, then 1/1 just yields 1 again and execution continues leftwards.
:  Duplicate the 1.
!  Print it.
:  Duplicate the 1.
|  Bitwise OR between 1 and 1 gives 1.
?  Try reading another integer. But we're at EOF, so this pushes 0.
   We're in a dead end, so the IP turns around and moves back to the right.
|  Bitwise OR between 1 and 0 gives 1.
   At this point, the state is exactly the same, as the first time we hit |, so from here
   on it's an infinite loop, printing two 1s per iteration.
\$\endgroup\$
3
\$\begingroup\$

Haystack, 15 12 bytes

0io=v
  ^1?|

Still working on a oneliner (if it's possible).

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

Squirrel, 48 bytes

local a=stdin.readn('b')-48;do print(a) while(a)
\$\endgroup\$
1 2
3
4 5
17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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