Christmas (programming) Challenge (2021)

via Stardot, a rather nice small-but-not-too-small programming challenge, by way of code-golfing.

The rules are quite nice: no sharing your code, or even your score, until the contest closes (which is tonight), and you can submit only once.

And you can use Basic or machine code, and even use the platform of your choice.

The challenge, then, is to produce exactly this output:
Image

(It might be interesting, once the deadline is over, to see the relative lengths of the best in class for 6502, Z80, 6809 and others.)

5 Likes

Challenge accepted. :slight_smile:

1 Like

Or BCPL … I mean - if that’s not a vintage programming language then what is! :wink:

-Gordon

Oh, absolutely - if we can compare Basic programs, then we can compare other languages too. APL will probably win though!

1 Like

A brainfuck program will win for sure. A sample “hello world” program is here.

++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
1 Like

Well, it’s late Sunday afternoon in California, but already after midnight GMT, so I guess I missed the deadline. My code is for the Apple 1, and is 76 bytes of machine language. You need about 176 keystrokes to enter it into WozMon, so it has to be broken into two lines.

80:D8 A9 FF 48 A9 1E 48 A9 FA 85 95 A2 4 A9 FE 85 92 A9 0 18 69 0 18 69 8 85 92 20 AE 0 CA D0 F0 E6 95 E6 95 30
:E4 A9 2 20 AE 0 A9 2 85 C2 A9 8D 20 EF FF A9 26 38 E5 C2 4A A8 A9 A0 20 C5 0 A0 0 A9 AA 20 EF FF 88 10 FA 60

It’s pure self-modifying code, with no tables.

image

I used a legal pad and a #2 pencil for development, and I assembled and debugged a slightly different version of it using the monitor and mini-assembler on an Apple ][ 'mulator before pasting it into an Apple 1 'mulator and executing.

Happy Holidays, Everybody!
<<< 6502 FOREVER!!! >>>

[Edit: The screenshot above has the tree a bit off-center to the right. Changing the value at location $B6 to a $26 or $25 centers it better.]

3 Likes

Next year add lights. :slight_smile:

Thanks for sharing! See also the stardot thread and perhaps the thread on 6502 for people’s various efforts. And of course eventually the competition page will show some of the submissions, I hope.

It will also be interesting to see results for other micros and other languages. (There’s already a PDP-11 program posted on stardot.)

Ok, I decided for a poetic effort in BASIC (for Commodore 8-bit), meaning, rather than optimizing for length (180 bytes including the REMark), I went for a festive underline decoration, nicely filled lines and a poem-like structure.

xmas2001_pet2001-listing

Mind that the bare algorithm looks something like this (122 bytes), putting into consideration that the argument passed to SPC() is truncated to integer anyway:

1 X$="************************"
2 READA:IFA>0THENPRINTSPC(20-A/2);LEFT$(X$,A):GOTO2
3 DATA1,3,5,7,3,7,11,15,5,11,17,23,3,3,0

Online link (type RUN and/or LIST): https://www.masswerk.at/pet/?data=…

2 Likes

Did anyone go for an algorithmic approach?
Mind that the tree consists of lines of 1+2*0*x, 1+2*1*x, 1+2*2*x, 1+2*3*x asterisks, where x = 1,2,3, and the final stem.

Pseudo-code:

for x = [1,2,3]:
    for y = [0,1,2,3]:
        for s = [0 .. center - y*x]:
            print " "
        for a = [0 .. 2*y*x]:
            print "*"
        print "\n"
/* print stem and end */

For those entertaining a closer interest in Michael’s 6502 code, here’s the disassembly:

                            * = $0080
0080   D8                   CLD
0081   A9 FF                LDA #$FF
0083   48                   PHA
0084   A9 1E                LDA #$1E
0086   48                   PHA
0087   A9 FA                LDA #$FA
0089   85 95                STA $95
008B   A2 04      L008B     LDX #$04
008D   A9 FE                LDA #$FE
008F   85 92                STA $92
0091   A9 00      L0091     LDA #$00
0093   18                   CLC
0094   69 00                ADC #$00
0096   18                   CLC
0097   69 08                ADC #$08
0099   85 92                STA $92
009B   20 AE 00             JSR L00AE
009E   CA                   DEX
009F   D0 F0                BNE L0091
00A1   E6 95                INC $95
00A3   E6 95                INC $95
00A5   30 E4                BMI L008B
00A7   A9 02                LDA #$02
00A9   20 AE 00             JSR L00AE
00AC   A9 02                LDA #$02
00AE   85 C2      L00AE     STA $C2
00B0   A9 8D                LDA #$8D
00B2   20 EF FF             JSR $FFEF
00B5   A9 26                LDA #$26  ;alternatively use #$25
00B7   38                   SEC
00B8   E5 C2                SBC $C2
00BA   4A                   LSR A
00BB   A8                   TAY
00BC   A9 A0                LDA #$A0
00BE   20 C5 00             JSR L00C5
00C1   A0 00                LDY #$00
00C3   A9 AA                LDA #$AA
00C5   20 EF FF   L00C5     JSR $FFEF
00C8   88                   DEY
00C9   10 FA                BPL L00C5
00CB   60                   RTS
                            .END
1 Like

Yes, @hoglet’s Basic approach uses multiplication:

10 FORX=1TO5:FORY=1TO4:A=X*Y:IFX>3A=2:Y=4
20 PRINTTAB(21-A)STRING$(A+A-1,"*"):NEXT,
1 Like

There’s also a one-liner by jgharston

2 FOR A=1 TO 3:FOR B=1 TO 4:PRINT SPC(20-B*A);STRING$(2*B*A-1,"*"):NEXT:NEXT:PRINT SPC(18)"***"'SPC(18)"***"

Aw, BBC-BASIC and its STRING$ command – this is unfair! :wink:
*) Meaning, in Commodore BASIC, we’d either have to define a base string to operate on (compare my “festive underline decoration”) or use FOR-NEXT loops to print the individual characters, which is much lengthier (both in code and runtime).

I did hope BBC Basic would show some extra strengths, not least because it’s twice the ROM - it’s a 16k Basic. Also, it’s later.

JGH could lose a few characters there, even before we start applying abbreviations:

2 FORA=1TO3:FORB=1TO4:PRINTSPC(20-B*A)STRING$(2*B*A-1,"*"):NEXT,:PRINTSPC18"***"'SPC18"***"

That’s 92 characters to type, 66 bytes in memory. Just 78 characters if we do this:

2F.A=1TO3:F.B=1TO4:P.SPC(20-B*A)STRI.2*B*A-1,"*"):N.,:P.SPC18"***"'SPC18"***"

Happy Midwinter!

$ ./xmas2.dc 
              *
             ***
            *****
           *******
             ***
           *******
         ***********
       ***************
            *****
         ***********
      *****************
   ***********************
             ***
             ***
$ cat xmas2.dc
#!/usr/bin/dc -f
[1-d0<_256*32+]s_
[1-d0<*256*42+]s*
[d30r-2/l_xPl*xPAP]s!
3 3 23 17 B 5 F B 7 3 7 5 3 1
[l!xz0<^]ds^x

…or (w)interactive at TIO.

I absolutely don’t claim this being the shortest dc solution. There possibly is room for improving this one, e.g. by merging the n-spaces and the n-stars macros or finding a total different approach.

3 Likes

Nice! “dc (desk calculator) is a cross-platform reverse-Polish calculator which supports arbitrary-precision arithmetic … one of the oldest Unix utilities, preceding even the invention of the C programming language.”

1 Like

I use building a (looong) number as kind of string$():

$ dc -e '[1-d0<*256*42+]s* 23l*x 16o p'
2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A

Like a memory image of some *s. And dc just prints it as that and AP prints LF:

$ dc -e '[1-d0<*256*42+]s* 23l*x P AP'
***********************

Commented dc code is definitely less scary, but the beauty of comments was not part of this coding puzzle.

1 Like

Well with shell programs, 3 keys and a click comes to mind.
Click on tree, select all, select cut, select paste, select trash can. copied exactly:)
Uinix people can | dev/null
Lots of great ways to print that tree. Good work people. Ben,

FWIW: Here is my BCPL version - edited, compiled and run on my Retro 65c816 CPU system with 512KB of RAM, clocked at 16Mhz:

I completely missed that an algorithmic approach was possible, as for esoteric approaches …

Cheers,

-Gordon

2 Likes

Is there any sense in which you could hand-code the CINTCODE, in an analogous way to writing in assembler? Perhaps just tweaking and optimising the compiler’s output?? (Not that this would necessarily be fun, but perhaps it might be…)

1 Like