8
\$\begingroup\$

When you run your program first, it should print an integer sequence. The second run should print the 'Mary had a little lamb' song. The third run should produce an ASCII image file.

Scoring

Your score will be the sum of your bytes of code and any file content at the start of each of the 3 runs. Lowest score wins.

For example, myprog is 1500 bytes and does not change its size, but writes a 4 bytes file each run so it knows what to do on the next run. The score would be 1500 + (1500+4) + (1500+4) = 4508.

Output

The first output is this sequence of 133 integers, separated by single spaces:

0 89 98 179 188 197 269 278 287 296 359 368 377 386 395 449 458 467 476 485
494 539 548 557 566 575 584 593 629 638 647 656 665 674 683 692 719 728
737 746 755 764 773 782 791 809 818 827 836 845 854 863 872 881 890 908
917 926 935 944 953 962 971 980 1079 1088 1097 1169 1178 1187 1196 1259
1268 1277 1286 1295 1349 1358 1367 1376 1385 1394 1439 1448 1457 1466 1475
1484 1493 1529 1538 1547 1556 1565 1574 1583 1592 1619 1628 1637 1646 1655
1664 1673 1682 1691 1709 1718 1727 1736 1745 1754 1763 1772 1781 1790 1808
1817 1826 1835 1844 1853 1862 1871 1880 1907 1916 1925 1934 1943 1952 1961
1970

The second output is this text exactly (including capitals, punctuation, and white space - the inconsistent punctuation is intentional):

Mary had a little lamb,
Little lamb, little lamb,
Mary had a little lamb,
Its fleece was white as snow

And everywhere that Mary went,
Mary went, Mary went,
Everywhere that Mary went
The lamb was sure to go

It followed her to school one day
School one day, school one day
It followed her to school one day
Which was against the rules.

It made the children laugh and play,
Laugh and play, laugh and play,
It made the children laugh and play
To see a lamb at school

The third output is this image in PPM ASCII(P3) format left in a file called blue.ppm. This is the image in PNG format:

target image

The PPM file should look something like this:

P3 50 50 255
255 255 255 255 255 255 255 255 255 255 255 255 ...
...
255 255 255

There is a copy of the full PPM file here.

Example run (on Linux)

# ls
myprog
# interpreter myprog
0 89 98 179 188 197 269 278 287 296 359 ...
# interpreter myprog
Mary had a little lamb,
Little ...
# interpreter myprog
# ls
blue.ppm
myprog
# cat blue.ppm
P3 50 50 255
255 255 255 255 255 ...

Rules

  • Your code may modify itself.
  • Running the program a fourth time is undefined behaviour.
  • You may write to a file in the current directory, but the size of this file will add to your score at the start of each run. The final PPM file is excluded from this.
  • The first two outputs are to stdout (or similar). The last output is written to a file, with nothing sent to stdout.
  • The first two outputs may optionally have a trailing white space character (e.g. space or line feed).
  • You may not use compression or image libraries. You may use your own compression or image functions but this code must be included in your program.
  • The standard loopholes are prohibited.
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Great problem ! Learnt quite a few new things while solving it. \$\endgroup\$ Commented Mar 8, 2015 at 13:49
  • \$\begingroup\$ Does the PPM file need to have 256 color steps or should it just be able to generate the same image? \$\endgroup\$
    – Oberon
    Commented Mar 10, 2015 at 21:23
  • \$\begingroup\$ Does the image output file has to be exactly like the one mentioned in the question or can there be differences in whitespaces ? This is vital to my answer as I have taken special care that the newlines are inserted at the right place every time. \$\endgroup\$ Commented Mar 10, 2015 at 22:06
  • \$\begingroup\$ @Oberon and Anmol Singh Jaggi, the PPM must be in P3 format and show the exact same picture as the PNG when viewed. The bit depth, internal white space is up to you, but it must be a valid file. \$\endgroup\$ Commented Mar 11, 2015 at 3:54

7 Answers 7

11
\$\begingroup\$

Ruby, 1356 1268 * 3 = 3804 bytes

if File.file?(?b)
s='P3
50 50
255
'
d=e=0
[153,44,6,1,42,1,6,1,42,1,6,1,42,1,6,1,42,1,6,1,42,1,6,1,42,1,4,40,5,1,4,1,1,1,36,1,5,1,4,1,1,1,36,1,5,1,4,1,1,1,36,1,5,1,4,1,1,1,36,1,5,1,4,1,1,34,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,34,1,3,1,5,1,4,1,8,31,5,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,1,25,1,9,1,4,1,8,37,4,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,1,34,1,14,36,63].map{|n|n.times{s+=[" 255 255 255"," 0 0 255"][d];s+=$/if (e+=1)%50==0};d=1-d}
File.write 'blue.ppm',s
elsif File.file?(?a)
puts [["","Mary had a ","little lamb",?,,?,,"Its fleece was white as snow"],["And ","everywhere that ","Mary went",?,,'',"The lamb was sure to go"],["","It followed her to ","school one day",'','',"Which was against the rules."],["","It made the children ","laugh and play",?,,'',"To see a lamb at school"]].map{|a,b,c,d,e,f|[a+b+c+d,c.capitalize+', '+c+d,b.capitalize+c+e,f]*$/}*"

"
`touch b`
else
1971.times{|i|$><<"#{i} "if i.to_s.chars.map(&:to_i).reduce(:+)%17<1}
`touch a`
end

To keep track of the invocation, I'm creating an empty file a on the first run and an empty file b on the second run.

  • The first program uses a certain property of the numbers.
  • The second program uses a bunch of reusable parts of the verses, but that currently only saves 100 bytes over naively printing the entire thing.
  • The third program currently uses just a simple run-length encoding. I'll look into actually encoding the path of the line later.
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Nice solution, especially the numbers (which is more of a math problem). You could save a few bytes if you replace i.to_s.chars.map(&:to_i).reduce(:+) with (j=i.to_s).sum-48*j.size \$\endgroup\$
    – blutorange
    Commented Mar 8, 2015 at 15:37
  • \$\begingroup\$ @blutorange Oh, that's neat. :) I still want to revisit the image generation. I'll work your suggestion into it when I do. \$\endgroup\$ Commented Mar 8, 2015 at 15:41
  • \$\begingroup\$ You only need to keep a part of your source file for the 2nd and 3rd runs but maybe it's not that much gain as the biggest part is part 3 currently. With run-length coding the run-length coded rows you could improve part 3 a lot. \$\endgroup\$
    – randomra
    Commented Mar 9, 2015 at 1:48
9
\$\begingroup\$

Python (897 + 814 + 386 = 2097)

Simple self-modifying answer. I'll have to refine the second run later.

def p(x):print x,
map(p,[0]+filter(lambda x:sum(map(int,`x`))==17,range(1971)))
#l="ittle lamb,";M="Mary ";w=M+"went";e="verywhere that "+w;s="chool one day";I="It followed her to s"+s+"\n";j="augh and play";i="It made the children l"+j;print M+"had a l"+l+"\nL"+l+" l"+l+"\n"+M+"had a l"+l+"\nIts fleece was white as snow\n\n"+"And e"+e+",\n"+w+", "+w+",\nE"+e+"\nThe lamb was sure to go\n\n"+I+"S"+s+", s"+s+"\n"+I+"Which was against the rules.\n\n"+i+",\nL"+j+", l"+j+",\n"+i+"\nTo see a lamb at school"
#print>>file("blue.ppm","w"),"P3 50 50 255"+' '.join(" %i"%(255-255*any(a<y<b and x==c or y==d and e<x<f for a,b,c,d,e,f in[(2,48,2,47,2,37),(9,48,36,9,27,37),(9,41,28,40,9,29),(0,41,10,1,9,49),(0,37,48,36,14,49),(2,37,15,3,2,16)]))*2+" 255"for x in range(50)for y in range(50))
import sys;x=file(sys.argv[0],"r+");y='#'.join(x.read().split('#')[1:]);x.seek(0);x.truncate();x.write(y)

Additionally, if run for the fourth time, it safely degrades to a NOP:

'.join(x.read().split('#')[1:]);x.seek(0);x.truncate();x.write(y)
\$\endgroup\$
1
  • \$\begingroup\$ That is going to be hard to beat. I was wondering when some sneaky self-modifying code would appear ;-) \$\endgroup\$ Commented Mar 11, 2015 at 18:13
2
\$\begingroup\$

Python 3, 1027 + 1028 + 1029 = 3084

0 or print('0 '+' '.join(str(i)for i in range(1971)if sum(map(int,str(i)))==17))
1 or print("""+$,
L$, l$,
+$,
Its fleece was white as snow

And e(@,
@, @,
E(@
The!was sure to go

#&
S&, s&
#&
Which was against the rules.

%l/,
L/, l/,
%l/
To see a!at school""".translate({43:'Mary had a l',36:'ittle lamb',40:'verywhere that ',64:'Mary went',35:'It followed her to s',38:'chool one day',47:'augh and play',37:'It made the children ',33:' lamb '}))
q=[153,44]+[e-63for e in b'E@i@E@i@E@i@E@i@E@i@E@i@CgD@C@@@c@D@C@@@c@D@C@@@c@D@C@@@c@D@C@@aB@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@a@B@D@C@G^D@C@G@X@H@C@G@X@H@C@G@X@H@C@G@X@H@C@G@X@H@C@G@X@H@C@G@X@H@C@GdC@a@M@a@M@a@M@a@M@a@M@a@M@a@M@a@M@a@M@a@M@a@Mc~?']
1 or open("blue.ppm","w").write("P3\n50 50\n255\n"+' '.join(q[r*2]*'255 255 255 '+q[r*2+1]*'0 0 255 'for r in range(140)).strip())
f=open(__file__);l=f.read();f.close();open(__file__,"w").write(l.replace("0 or","0 and",1).replace("1 or","0 or",1))

Uses OEIS A166370 for the numbers, some hand-written compression for Mary's Lamb and ASCII bytes to store the amounts of numbers in the PPM.

(Ab)uses Python's feature to only evaluate the second value for logical operators if the result is not known yet (short-circuiting): 1 or code and 0 and code do not evaluate code. Then uses some replacements to change the 0 or enabling code execution to a 0 and and the next 1 or to 0 or.

The 3rd execution kills the second replace, as there are no more 1 or's. The 4th execution kills the first replace, after which the code does basically nothing.

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

C++, 1204 * 3 = 3612 bytes

Compiler used - GCC 4.9.2 with -std=c++14 flag

#include<bits/stdc++.h>
int i,j,c;
using namespace std;int main(){fstream f("F"),g("G");if(!f){while(i<=1970){j=i,c=0;while(j)c+=j%10,j/=10;if(c==17||i==0)cout<<i<<" ";i++;}ofstream f("F");}else if(f&&!g){cout<<R"(Mary had a little lamb,
Little lamb, little lamb,
Mary had a little lamb,
Its fleece was white as snow

And everywhere that Mary went,
Mary went, Mary went,
Everywhere that Mary went
The lamb was sure to go

It followed her to school one day
School one day, school one day
It followed her to school one day
Which was against the rules.

It made the children laugh and play,
Laugh and play, laugh and play,
It made the children laugh and play
To see a lamb at school)";ofstream g("G");}else{ofstream F("blue.ppm");F<<"P3 50 50 ";vector<int> L={1,2,4,10,13,16,19,25,28,43,76,103,109,127,190,460};vector<string> R={"1","?","43","10","6","161=","1","14","39","10","4","1514121<","1","151412","33","10","12","1315141;","1","13151417","30","10","1","1514171","7",":1814171","36","01","1","41","11",";191","35","01","1",">"},C={"255","0"};string r;i=j=0;while(i<R.size()){stringstream S(R[i]);S>>c;while(c--)r+=R[i+1];i+=2;}i=0;while(i<r.size()){c=L[r[i]-48];while(c--){F<<C[j]<<" ";}j=1-j;i++;}}}

Explanation -:

#include<bits/stdc++.h>
using namespace std;

int main()
{
    fstream f( "F" ), g( "G" ); // Creating empty files so that the program can decide when to run which task

    /**************************** TASK 1 ****************************/

    if ( !f ) // Print all the numbers within the range whose sum of digits is 17
    {
        for ( int i = 0; i <= 1970; i++ )
        {
            int j = i, c = 0;
            while ( j )
            {
                c += j % 10, j /= 10;
            }
            if ( c == 17 || i == 0 )
            {
                cout << i << " ";
            }
        }       
        ofstream f( "F" );
    }

    /**************************** TASK 2 ****************************/

    else if ( f && !g )  // Print the second task as it is using raw literals
    {
        cout << R"(Mary had a little lamb,
Little lamb, little lamb,
Mary had a little lamb,
Its fleece was white as snow

And everywhere that Mary went,
Mary went, Mary went,
Everywhere that Mary went
The lamb was sure to go

It followed her to school one day
School one day, school one day
It followed her to school one day
Which was against the rules.

It made the children laugh and play,
Laugh and play, laugh and play,
It made the children laugh and play
To see a lamb at school)";

        ofstream g( "G" );
    }

    /**************************** TASK 3 ****************************/

    else // Third task using Run-Length encoding
    {
        ofstream F( "blue.ppm" );
        F << "P3 50 50 ";

        /*
        L = set of all the lengths found during run-length encoding.
        R = vector containing the run-length encoding of "255" and "0" alternatingly.
                {1,"?") means 1 times print '255'/'0' "x" number of times where x = L[ASCII(?)-48] = L[15] = 469
        C = vector containing the two strings to be printed alternatingly.
        */

        vector<int> L = {1, 2, 4, 10, 13, 16, 19, 25, 28, 43, 76, 103, 109, 127, 190, 460};
        vector<string> R = {"1", "?", "43", "10", "6", "161=", "1", "14", "39", "10", "4", "1514121<", "1", "151412", "33", "10", "12", "1315141;", "1", "13151417", "30", "10", "1", "1514171", "7", ":1814171", "36", "01", "1", "41", "11", ";191", "35", "01", "1", ">"};
        vector<string> C = {"255", "0"};
        string r; // Contains the normal/expanded version of R
        i = j = 0;

        while ( i < R.size() ) // Expanding "R" into normal form and putting it into "r"
        {
            stringstream S( R[i] );
            S >> c; // Convert R[i] to its integer representation and put it in "c" with the help of stringstream.
            while ( c-- )
            {
                r += R[i + 1];
            }
            i += 2;
        }

        i = 0;
        while ( i < r.size() )
        {
            c = L[r[i] - 48];  // "c" is the number of times the current character has to be printed consecutively.
            while ( c-- )
            {
                F << C[j] << " ";
            }
            j = 1 - j; // Alternate "255" and "0"
            i++;
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

PHP (1552*3)+2 = 4658

There is A LOT of golfing that can be made.

The code writes 1 byte into another file called z, to check the status.

Here is the code:

<?$Y=base64_decode;$Z=gzdecode;$r=file_put_contents;switch(include z){case 2:$M=Mary;$l=lamb;$L=ittle;$H="$M had a l$L $l,";echo"$H
L$L $l, l$L $l,
$H
Its fleece was white as snow
";$W="$M went";$H="verywhere that $W";echo"
And e$H,
$W, $W,
E$H
The $l was sure to go
";$S=chool;$O="$S one day";$I="
It followed her to s$O";echo"$I
S$O, s$O$I
Which was against the rules.";$L="augh and play";$I="
It made the children l$L";echo"$I,
L$L, l$L,$I
To see a $l at s$S";$r(z,3);break;case 3:$r($Z($Y("H4sIAAAAAAAAA+3ay63CMBSE4X2qSAkRKH3QfzXAmkf8mBOfiX9dRXcBfIJ47Ewwj/uyb+u+Lbd9fx+r4gACAgICApoO2l5/Jf+X0icCfT4gG7ka0DSQQMdPOopB9bv5BpqeG6D2F8tjQK6AImJAroAiYkCugCJiQK6AemKQ51bWF+oaxe6Rk2DhAQUKjIIEIU9Xg8gTkBIiT0BKKG+e8nXMcVBRDFr3oyQIq4ADVLW1JNnfbEYkafYcJR+oatZLtrebEfluPVAAVDNKkn3yZoQfazhAvXkaW4WNTvQkEIUcSAlRyIGUEIUcSApRyIGUEIUcSAlRyIGUEIUcSAlRyH+/w/H7qudDXUHMf+nhpq4NGlM28196KOFtx5iy6XPpyTdiyaEhZdPg3p0S3gaN+baOAnVViAKV6bz4QxSoTOflAhAF6v95yfdVTT7otOEPCSNQ+Sgl/1jc9RhAhrOfux8HyG/2Gy6xE0J+v+AyXGInhAxnv98SOyFkOPspWA6Q3+w3XGInhChYQBGQ4ez3W2InhAxnPwXLAfKb/RfYvQqH8o0aENBJ0BPXPoC/PXEAAA==")),'blue.ppm');$r(z,1);break;default:echo$Z($Y("H4sIAAAAAAAAAxXSuQHAMAwCwFUYIehF+y8WXCWWaDj7gw4ncA+Uv7eIOcQKIf/fIPuQI+QuUj5fo+pQLdQsagclz67QeegSuhc9g95Gy/NLTBwmhanF9GCmMVsYeXeB5WFD2FxsDbYbO4XdxMr7I/QdREGxUA5UDXVBk9AGJGfuw33CcXExuGxcFa4TN4FbuvIHfq/091p/rk26N+nipN7R1RnuznB5htsz9GbuzzQA0wJMEzBtwNRbWIFlBpYdWIZgWYJlCpbe1hhsa7DNwbYH2yBsi7BNwtaLGIVjFY5ZOHbhGIZjGY5pOLbh6OWswzUPl+8+DcS1ENdEXBtxjcS1kku+sJ0oQ1GWokxF2YoyFmUtylzG4HsbDt/n3NG5C+cunbty7tq5G7738/3WJLxlVAIAAA=="));$r(z,2);}

I know that this is a VERY horrible code and I can try to golf the list.

But hey, I can't find a pattern on those :/

\$\endgroup\$
4
  • \$\begingroup\$ I can see that you have compressed the image in the last line, and minimised the size of the lamb song on the other lines, but I can't see where the integer sequence is. I need some guidance. \$\endgroup\$ Commented Mar 11, 2015 at 17:56
  • \$\begingroup\$ @CarpetPython More compression. It's the last part. \$\endgroup\$ Commented Mar 11, 2015 at 18:01
  • \$\begingroup\$ Thanks. If your are looking for the pattern in the integer sequence, some of the other answers may give you some clues. eg: the digits of the numbers have an interesting property. \$\endgroup\$ Commented Mar 11, 2015 at 18:20
  • \$\begingroup\$ @CarpetPython I'm not a copy-cat. But I did took a look at the other answers, but still couldn't find the pattern. \$\endgroup\$ Commented Mar 11, 2015 at 19:51
1
\$\begingroup\$

Ruby, 691+612+225 = 1528 bytes

Another self modifying answer, this time in ruby. I just bumped into this yesterday and the compressing of the poem caught my eye. I was only able to save 92 bytes off the raw text thought.

puts (0..1970).select{|i|eval(i.to_s.gsub /\B/,'+')%17<1}*' '
File.write $0,%@
m='lamb:little 0,:Mary :2had a 1:2went:laugh and play:It made the children 5:It followed her to 10: was : that :11 one day:school:everywhere:3
1 1
3
Its fleece8white as snow

And 1294,
4, 4,
1294
The 08sure to go

7
10, 10
7
Which8against the rules.

6,
5, 5,
6
To see a 0 at 11'
12.downto(0){|i|m.gsub! i.to_s,m.split(':')[i]}
puts m.split(':')[13].gsub /^./,&:upcase
File.write $0,%!a=[1]
s=[16,13]
File.write 'blue.ppm',(' P3
50 50 '+[460,a*43,[19,127]*6,13,a*39,[s,4,109]*4,s,4,a*33,10,s,[103,10,s]*12,25,a*30,s,25,[76,28,13,25]*7,a*36,13,[103,43]*11,a*35,190].flatten.map{|i|('255 '*i)+'0 0 '}*' ')[1..-6]!@

Each run of the program rewrites the program for the next run. I didn't figure out the special property of the numbers until looking over the other answers. And did take same inspiration Martin's answer but I didn't use the suggestion from blutorange because I couldn't figure out why it worked.

There is probably a few more bytes to scavenge from the poem but not much. It is basically just subbing in common sequences and is using the order of the sequence as the part to replace.

For the final part I length encoded all of the 255 bytes into an array and glued them together with the zeros. And then I encoded the repeating sequences in that array.

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

JavaScript + HTML, 3909 bytes

This is a HTML/JavaScript application that uses page reload to rerun files. I goofed on parsing the PPM. If you know how to read PPM files, please let me know. Stack Exchange doesn't allow local-storage. So you will have to run the JSFiddle.

Again, I know I bombed the ppm file.

But in the end:

JavaScript: 1,232 bytes * 3 = 3696

HTML: 71 bytes * 3 = 213

Total: 3909

JSFiddle

var mary = '</br>\
Mary had a little lamb,</br>\
Little lamb, little lamb,</br>\
Mary had a little lamb,</br>\
Its fleece was white as snow</br>\
</br>\
And everywhere that Mary went,</br>\
Mary went, Mary went,</br>\
Everywhere that Mary went</br>\
The lamb was sure to go</br>\
</br>\
It followed her to school one day</br>\
School one day, school one day</br>\
It followed her to school one day</br>\
Which was against the rules.</br>\
</br></br>\
It made the children laugh and play,</br>\
Laugh and play, laugh and play,</br>\
It made the children laugh and play</br>\
To see a lamb at school\
';
var img = '<img src="https://i.sstatic.net/sHCba.png"/>'

function run() {
  var step = localStorage.getItem("step");
  step++;
  localStorage.setItem("step", step);
  $('#step').text(step);
  var r = $('#results')
  switch (step) {
    case 1:
      for (var i = 0; i < 133; i++) {
        r.append(i + 1 + ' ');
      }
      break;
    case 2:
      r.html(mary);
      break;
    case 3:
      r.html(img);
      localStorage.setItem("step", 0);
      break;
    default:
      localStorage.setItem("step", 0);
      break;
  }
}
run();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>Step: <span id='step'></span>
</label>
<div id='results'></div>

\$\endgroup\$
2
  • \$\begingroup\$ Hi @Neoaptt and welcome to PPCG. You might need to read the question carefully to make sure your answer meets the requirements. Your integer sequence does not match the required sequence, and the image is not written to a file in PPM format. The point of the question is to challenge you to store the three outputs in a compressed way inside your program, by exploiting patterns. Also not that downloading files from the network is one of the 'standard loopholes' prohibited in the question. \$\endgroup\$ Commented Mar 11, 2015 at 18:08
  • \$\begingroup\$ You can read up on these loopholes at meta.codegolf.stackexchange.com/questions/1061/…. \$\endgroup\$ Commented Mar 11, 2015 at 18:10

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.