Y2K... in 2019?

18

1

It's August 10th, 2019, but your task still involves Y2K. Weird, right?

Create a program that prints itself, with a two digit number appended to it. The first time you run it, it should append 00 to its output (its source code, because this is a quine variant). When you run that output, the original program without a two digit number, it should output the original program, but with 01 appended to it. Run that output to get the OG program with 02 appended, then that to get the program with 03... This chain should continue until 99. That program should output BREAKING NEWS: WORLD ENDS.

If your program is Y2Kparanoia: yes then:

  1. It should output Y2Kparanoia: yes00
  2. That output should print Y2Kparanoia: yes01
  3. That output should print Y2K paranoia: yes02
  4. Repeat until step 100: this program outputs the doomsday news specified

This is code golf, so the shortest program that can print itself while following these steps wins.

Andrew

Posted 2019-08-10T14:10:47.530

Reputation: 2 067

7According to the description the 99th time we run we'll be running 2Kparanoia: yes97 and producing 2Kparanoia: yes98, so shouldn't (4) read Repeat to step 100, but step 101 will output "BREAKING NEWS: WORLD ENDS"? (i.e. 2Kparanoia: yes99 produces the news) – Jonathan Allan – 2019-08-10T16:51:49.330

Answers

7

Perl 6, 122 114 106 bytes

-8 bytes thanks to Shelvacu

END {<print $!-199??"END \{<$_>~~.EVAL};\$!="~($!-1&&$!-99)+100!!"BREAKING NEWS: WORLD ENDS">~~.EVAL};$!=1

Try it online!

Takes the standard quine format and adds the breaking news string as well as a new function call with the appended number. This uses END to execute the function when the program ends.

Jo King

Posted 2019-08-10T14:10:47.530

Reputation: 38 234

You can save 3 more bytes by using END and an our variable: END {<print $s-199??"END\{<$_>~~.EVAL};our\$s="~($s-1&&$s-99)+100!!"BREAKING NEWS: WORLD ENDS">~~.EVAL};our$s=1 – Shelvacu – 2019-08-11T05:29:13.057

For now, this is the current winner. – Andrew – 2019-08-12T09:25:17.297

7

Ruby, 158 154 146 128 122 100 bytes

Inspired by this answer.

eval s=%{$><<(D>198?'BREAKING NEWS: WORLD ENDS':'eval s=%%{%s}<<D=%d'%[s[0..-2],D<2?100:D+1])#}<<D=1

EDIT: I was able to remove (s.split(35.chr)[0]+35.chr).inspect and replace it with s[0..-2] (range of every value except the last) and the %{ ... } string syntax I used before. Saved 22 bytes!

Old version:

EDIT: Saved a pair of parens (and corresponding pair in the data section) by realizing that "BREAKING NEWS: WORLD ENDS" is a perfectly valid format string, and ruby ignores any extraneos parameters.

END{$><<(q=S>198?"BREAKING NEWS: WORLD ENDS":%{END{$><<(q=S>198?"BREAKING NEWS: WORLD ENDS":%%{%s})%%[q,S<2?0:S-99]}
S=1%02d})%[q,S<2?0:S-99]}
S=1

When starting this I realized that since the number has to go at the very end of the program, and ruby doesn't allow using variables before they are declared, I would have to make code run after the digits somehow. I could've done something like def a(s) ... end;a 1 which would become ...end;a 100, however using ruby's lesser-known END syntax uses fewer bytes. However, the block inside END is in a different scope, so S must be a global variable or constant.

Explanation:

  • END{ ... };S=1: Run block of code just before program terminates; Set constant S to 1 (or 100 - 199 in future iterations)
  • $><<( ... ): $> is a shortcut in ruby for stdout, and << on an IO writes to the IO. The parens are required, otherwise it becomes ($><<S)>198...
  • S>198?"BREAKING NEWS: WORLD ENDS":(q=...)%[q,S<2?0:S-99]: If I were to break this out into slightly more reasonable code it would be:

    if S > 198
      "BREAKING NEWS: WORLD ENDS"
    else
      q = ...
      number_to_append = if S < 2
        0
      else
        S - 100 + 1
      end
      q % [q, number_to_append]
    end
    

    The % operator applied to a string is effectively printf, with the LHS being the format string and the RHS being the arguments.

  • %{ ... (q=%%{%s}) ... S=1%02d}: ruby has an interesting syntax for strings that also allows for pairs of curly brackets to appear within the string without any escaping as long as they are balanced. This is very helpful, as otherwise a similar quine would have to escape the string to put it into itself as a string literal. The two substitutions in the format string are %s for a regular string and %02d for a number right-padded to a size of 2 with the character 0.

My thoughts on shortening further:

  • It'd be nice to be able to use s instead of $s, but defining s s=$s; or making a function def a(s) ... both use more bytes than they save, and I can't think of any other way to do it. EDIT: Constants are global and can be one character!
  • It'd be nice if S was always less then 100, so that it could be compared using 2-digit numbers instead of 3-digit numbers. However, if I use S=0 at the end, the next two digits are interpreted as octal, and 8 and 9 are invalid and all is bunk. S= simply isn't valid, and I don't know any other way to make a value valid both before and after appending two digits. Of note, 0 (and every other integer) is truthy in ruby.

Any thoughts on how to make this shorter, please let me know!

Try it online!

Shelvacu

Posted 2019-08-10T14:10:47.530

Reputation: 610

Maybe if you used s=100-1? Then s will be 99, 0, -1...-99, and -s will be -99, 0...99. – Purple P – 2019-08-11T17:17:51.640

@PurpleP No matter how I try I can't figure any way to do that and save characters. – Shelvacu – 2019-08-12T06:57:28.660

5

Go, 382 366 354 340 305 298 272 bytes

Won't win but I had fun with the challenge.

package main
func main(){if n<199{s+="\x60,"
print(s[:135],s,100+(n/100)*(n%100+1))}else{print("BREAKING NEWS: WORLD ENDS")}}
var s,n=`package main
func main(){if n<199{s+="\x60,"
print(s[:135],s,100+(n/100)*(n%100+1))}else{print("BREAKING NEWS: WORLD ENDS")}}
var s,n=`,1

Try it on the Go Playground!

Based on a quine. If the variable n is less than 199, then it adds to the string variable n a grave accent (\x60), Go's character for multiline strings, followed by a comma ,. It continues by printing the first 147 characters of s (to prevent printing the , because that only occurs at the end) then prints s as a whole, and finally prints 100 if n == 1 and n+1 otherwise. The result is that successive runs change the variable n at the end of the program to 100, 101, etc. If the variable n is 199 or more, then it prints breaking news.

Purple P

Posted 2019-08-10T14:10:47.530

Reputation: 919

3

Haskell, 240 232 218 216 bytes

p=putStr;h 1=100;h k=k+1;g _=p$"n="++show(h n);main|n>198=p"BREAKING NEWS: WORLD ENDS"|1>0=p<>print<>g$"p=putStr;h 1=100;h k=k+1;g _=p$\"n=\"++show(h n);main|n>198=p\"BREAKING NEWS: WORLD ENDS\"|1>0=p<>print<>g$"
n=1

Try it online!

Adapted from a quine

B. Mehta

Posted 2019-08-10T14:10:47.530

Reputation: 763

2

JavaScript (ES6), 116 bytes

setTimeout(s="alert((n-1?++n:n=100)-200?`setTimeout(s=${JSON.stringify(s)}),n=`+n:'BREAKING NEWS: WORLD ENDS')"),n=1

94 bytes, if stringifying functions is allowed

f=_=>((p=`f=${f}`.split`|`)[4]=p[4]-1?-~p[4]:100)-200?p.join`|`:'BREAKING NEWS: WORLD ENDS'||1

Herman L

Posted 2019-08-10T14:10:47.530

Reputation: 3 611

2

You can't read your own source code (f=${f}), that's not a quine according to https://codegolf.meta.stackexchange.com/a/4878/13400

– Shelvacu – 2019-08-11T16:02:57.310

1

C# (Visual C# Interactive Compiler), 193 bytes

x=>{var a=t>198?"BREAKING NEWS: WORLD ENDS":"x=>{{var a=t>198?{1}BREAKING NEWS: WORLD ENDS{1}:{1}{0}{1};Write(a,a,(char)34,t+(t<2?99:1));}};int t={2}";Write(a,a,(char)34,t+(t<2?99:1));};int t=1

Try it online!

Embodiment of Ignorance

Posted 2019-08-10T14:10:47.530

Reputation: 7 014

1

Pyth, 81 80 bytes

.vh,K"?>J198\"BREAKING NEWS: WORLD ENDS\"s[\".vh,K\"N:KN+C92NN\"J\"?<J2*TT+J1"J1

Try it online!

Explanation:

.vh,K" ... "J1
.v               Eval pyth code
  h              Get the first item in list
   ,             Make a list of the next two items
            J1   Set J = 1 (J = 100 to 199 in future iterations)
    K" ... "     Set K to the given string

And the code in the string is (breaking news shortened):

?>J198"BNWE"s[".vh,K"N:KN+C92NN"J"?<J2*TT+J1
?                                              Ternary: If A then B else C
 >J198                                         Test if J > 198
      "BNWE"                                   String literal; If ternary was true, return this (which is then implicitly printed)
            s[".vh,K"N:KN+C92NN"J"?<J2*TT+J1   ternary else
            s                                  concatenate list of strings
             [                                 create list
              ".vh,K"                          string literal, list[0]
                     N                         N is set to the double-quote character, list[1]
                      :KN+C92N                 list[2]
                      :                        Regex substitution. In A, replace B with C
                       K                       Variable K (set to the string being eval'd)
                        N                      N is double-quote
                         +C92N                 A backslash followed by a double-quote
                         +                     concat two strings
                          C92                  character with code point 92 (backslash)
                             N                 N is double-quote
                              N                N is double-quote, list[3]
                               "J"             String literal, list[4]
                                  ?<J2*TT+J1   Inner ternary, list[5]
                                   <J2         If J < 2 ..
                                      *TT      return T * T (10 * 10), else
                                          +J1  return J+1

Shelvacu

Posted 2019-08-10T14:10:47.530

Reputation: 610