20
\$\begingroup\$

Your task is to create a program that outputs the string:

Hello, Toroidal Earth!

with an optional trailing newline.

Additionally if I remove the first line1 of your program and add it as a line after the end of your program the new program should be a valid solution to this challenge in the same programming language.

So if my program were:

use module System.IO, Types.String
begin IO with (input as stdin, output as stdout)
new "Hello, Toroidal Earth" >> toBytestream >> output
end IO closing streams

then, its shift:

begin IO with (input as stdin, output as stdout)
new "Hello, Toroidal Earth" >> toBytestream >> output
end IO closing streams
use module System.IO, Types.String

would also have to be a valid solution, meaning that the next shift:

new "Hello, Toroidal Earth" >> toBytestream >> output
end IO closing streams
use module System.IO, Types.String
begin IO with (input as stdin, output as stdout)

would also have to be a valid program. And so on ad infinitum.

Likewise if I remove the final column of the program and insert it before the first column the result must be a valid solution to this challenge in the same programming language. When removing a column if a row doesn't have a character in that column (i.e. it is too short) then you should treat that place as a space character. So for example if my program were:

use module System.IO, Types.String
begin IO with (input as stdin, output as stdout)
new "Hello, Toroidal Earth" >> toBytestream >> output
end IO closing streams

Then the program:

 use module System.IO, Types.String
 begin IO with (input as stdin, output as stdout)
tnew "Hello, Toroidal Earth" >> toBytestream >> outpu
 end IO closing streams

should also be a valid solution, and of course any further shifting of it either vertical or horizontal should be as well.

All in all these shifts represent rotations on a torus.

Answers will be scored in bytes with fewer bytes being better.

1: You may choose to have your lines delimited by '\n' or by '\r\n'. Probably the former.

\$\endgroup\$
7
  • 1
    \$\begingroup\$ What if your program is one line only? That'd just make it always valid no matter what? Or am I missing something? \$\endgroup\$
    – 0xff
    Aug 25, 2021 at 13:49
  • 8
    \$\begingroup\$ @Jadefalke You are allowed to have 1 line programs. However they still require the column rotations to work. \$\endgroup\$
    – Wheat Wizard
    Aug 25, 2021 at 13:59
  • \$\begingroup\$ Does it have to be a full program? \$\endgroup\$
    – 0xff
    Aug 25, 2021 at 14:44
  • 1
    \$\begingroup\$ @Jadefalke There are no special rules in terms of input and output for this challenge. Whatever is allowed by default is allowed for this challenge. \$\endgroup\$
    – Wheat Wizard
    Aug 25, 2021 at 14:46
  • \$\begingroup\$ Column rotation? I'm interested to see if any programming language will survive this for a multi-line program. \$\endgroup\$
    – Corey
    Aug 26, 2021 at 0:41

7 Answers 7

21
\$\begingroup\$

Cascade, 36 bytes

@l"
}
"""
ETH
aoe
rrl
tol
hio
!d,
"a

Try it online!

While Cascade programs default to starting in the top left, but an explicit starting point can be created using a single @. This makes the program pretty much entirely immune to any column or row shifts, since all execution wraps around the edges of the playing field like a torus anyway. Note that if you had multiple @s, they would be triggered in order of appearance in the program, no longer preserving the behaviour.

The naive way of printing a string would be to print it all in one column, however that totals up to 49 bytes because of all the newlines. Instead, I split the string into three parts (coincidentally at each word, and execute each one by (ab)using }. One last consideration is put into where the string is split, so the spaces are at the end of the line, saving bytes by leaving them to be implicitly filled in by the interpreter.

\$\endgroup\$
20
\$\begingroup\$

Unary,

Rev 0 3121491355794998332440739552097977007353231296357070843005722815009035246433220686378881420659391378316482528838109777011691037239240361352724200445025302725444438163079585978557249556

Rev 1 276014140987112321091243548089349059271143856599044292139902575100947961955482006878466337854296695443646817751973462391672878955178246166009852634302332948 bytes

Unary is an encoding for brainfuck programs where each of the 8 characters that can be used in a valid program corresponds to an octal digit. The program is converted to an octal number n, then the Unary output is composed of n identical characters (usually 1's.) Since all characters are the same, it is a valid submission for this challenge. See this question for Brainfuck/Unary converters.

The underlying Brainfuck programs (not valid submissions) are below

brainfuck, Rev 1, 172 bytes

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

Try it online!

brainfuck, Rev 0, 203 bytes

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

Try it online!

\$\endgroup\$
1
  • 4
    \$\begingroup\$ The revision gives 3.12e183 bytes saved, which I think is a personal record! I'm surprised how upvoted this is, despite (or perhaps because of) the fact that the score is so high. Thanks! \$\endgroup\$ Aug 26, 2021 at 21:47
14
\$\begingroup\$

Prolog (SWI), 107 bytes

.                                :-write("Hello, Toroidal Earth!")
A.
:-write("Hello, Toroidal Earth!").
A.

Try it online!

SWI doesn't exactly mind syntax errors, so we create two lines which each print the text and overlap by one character. That way when the are roatated there is always exactly one of them intact.

We have to add the A.s in between lines because without a . the SWI parser can get confused. For example if we remove them in the starting program

.                                :-write("Hello, Toroidal Earth!")
:-write("Hello, Toroidal Earth!").

The parser doesn't recover from the fail state quick enough to properly parse the second line. . seems to be more or less a hard override that tells it to give up on the clause.

\$\endgroup\$
12
\$\begingroup\$

Fission, 26 bytes

R"Hello, Toroidal Earth!";

Try it online!

Unfortunately, Fission is so good at this we don't need to do anything interesting. R creates an atom which moves towards the right. As the atom reaches other characters, it executes them. The first character it hits is " which activates string mode, in which each further character encountered is output, except " which deactivates it. Then, ; ends the program. Fission's layout is toroidal by default for atoms, so a shifted program like:

l Earth!";R"Hello, Toroida

Try it online!

behaves exactly the same.

\$\endgroup\$
11
\$\begingroup\$

Lost, 63 58 67 bytes

%?\>>>>>>>>>>>>>
>>\"Hello,vV"-+v
v-">^ladioroT"<<
\+x"EarthvU"-+@v

Try it online!

My first try with Lost. This is a 2D language, where the starting position and direction are random. So you never know where the instruction pointer starts and where it goes, but you can direct it. The instruction pointer moves in a toroidal way, meaning that if it reaches the end of a line, it starts the same line again. Likewise with columns.

Unfortunately, there is a bug in Lost, that will prevent it from running, when it starts with a space character. So I had to edit it to have no spaces in it and to have equally long lines, resulting in nine bytes more than my previous answer.

Explanation: A good portion of the code is just for directing the ip to the start of the code (>, <, v, and ^ instruct the ip to go to that specific direction. "" is a mirror, so the ip will reflect in the intentional way). The code starts in the upper left corner.

% deactivates the "safe mode". After that, the code will end, when it reaches the @.

?\ will start a loop, that empties the stack. (The ? means "if the stack is not empty, pop an item and ignore the next command"). When the stack is empty, the \ will reflect the ip into the second line.

\ reflects the ip to the right.

"Hello,vV" pushes that exact string onto the stack. The v is needed to direct the ip to the start, if it starts within the string.

-+ means "invert the last item on the stack and add the last two items together. Basically, it pushes 'v' - 'V' = ' '.

Then the ip is redirected into the third row, where it pushes "Toroidal^>" and again calculates '^' - '>' = ' '.

In the last row it pushes "EarthvU" and calculates 'v' - 'U' = '!'.

Then, the @ is the end of the code. The contents of the stack are printed implicitly.

\$\endgroup\$
0
10
\$\begingroup\$

CSS, 280 bytes

:after{content:""}"{}:after{content:""}"{}:after{content:""}"{}
body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}

Try the default one:

:after{content:""}"{}:after{content:""}"{}:after{content:""}"{}
body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}

Try all (WARNING: This may hang your browser!):

const source = String.raw`
:after{content:""}"{}:after{content:""}"{}:after{content:""}"{}
body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}body:after{content:"Hello, Toroidal Earth!"}"{}/*/}{}
`.trim();

const lines = source.split('\n');
const width = Math.max(...lines.map(x=>x.length));
const height = lines.length;

for (let i = 0; i < width; i++) {
  for (let j = 0; j <= height; j++) {
    const modify = lines.slice(j).concat(lines.slice(0, j))
      .map(line => line.padEnd(' ', width).slice(i) + line.slice(0, i)).join('\n');
    const iframe = document.body.appendChild(document.createElement('iframe'));
    iframe.style = 'width: 100%; height: 60px;';
    iframe.src = 'data:text/html;base64,' + btoa(`<style>${modify}</style>`);
  }
}

The story tells us: You should repeat something 2 3 4 times whenever it is important.

Also, I have no idea how to golf it.

(I'm using Firefox 91, if this matters.)

\$\endgroup\$
1
  • \$\begingroup\$ The story tells us: you should repeat something 2-4 times whenever it is important. \$\endgroup\$ Aug 27, 2021 at 10:03
5
\$\begingroup\$

R -e 'options(error=function(){})', 183 bytes

(or any other R environment in which errors do not halt execution of subsequent commands: entering the program into the R interactive console (or Rstudio) works fine; in batch mode or TIO we can set the global enviroment option error to an empty function; or in Rscript we can set this using the command-line option -e 'options(error=function(){})').

if(F)  cat("hello toroidal world")#"                                   F=!F;
    F=!F		                  
                                   `if`(F,cat("hello toroidal world"))#"
F=!F

Try it online!

Try all vertical rotations
Try all horizontal rotations

How?

The program is based offset copies of the code if(F)cat("hello toroidal world")#" and F=!F. The first instance of if(F)cat("hello toroidal world")# shouldn't output anything (since F is the built-in variable for FALSE). Then, F is flipped to !F = TRUE, so the second instance writes the output.
The final line flips F to !F again, to ensure that any vertical rotation of the lines leaves the overall program function unchanged.

But what if we rotate the code horizontally?

Most rotations that cut the first line will cause it to fail, but the second line will still flip F to !F so the third line will output Ok.
The exceptions are rotations of 5, 6, or 7 characters, which will remove the if(F) at the start of the first line, so the cat function will be called: however, the F=!F on the second line is placed so that any of these rotations will break it, with the result that the cat function on the third line will now not be called.

Any rotations that cut the third line (and so could cause it to fail) will bring the extra F=!F at the end of the first line, which is otherwise commented-out, to the front of the line, so the first line will now output.


R -e 'options(error=function(){})', 80 bytes

cat("hello toroidal world")
)                         cat("hello toroidal world"

Try it online!

...then I read the other answers and realised that a simple port of Wheat wizard's Prolog answer is much cleaner and shorter... Oh, well...

\$\endgroup\$

Your Answer

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

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