Christmas (programming) Challenge (2021)

The challenge there (hand-coding Cintcode) is that there isn’t a separate assembler for it (yet?) The compiler keeps it internally but it can generate the cintcode for checking… This is the output:

Ruby BCPL (10 Oct 2014) with simple floating point
   0:  DATAW #x00000000
   4:  DATAW #x0000DFDF
   8:  DATAW #x6F68730B
  12:  DATAW #x61724277
  16:  DATAW #x2068636E
// Entry to:   showBranch 
  20: L2:
  20:     LL  L1
  22:    XCH  
  23:    SUB  
  24:     L2  
  25:    DIV  
  26:    SP4  
  27:     L1  
  28:    SP5  
  29:    XCH  
  30:    SP6  
  31:    JGR  L5
  33: L4:
  33:      L   32
  35:    K7G   41
  37:     L1  
  38:    AP5  
  39:    SP5  
  40:    LP6  
  41:    JLE  L4
  43: L5:
  43:     L1  
  44:    SP5  
  45:    LP3  
  46:    SP6  
  47:    JGR  L7
  49: L6:
  49:      L   42
  51:    K7G   41
  53:     L1  
  54:    AP5  
  55:    SP5  
  56:    LP6  
  57:    JLE  L6
  59: L7:
  59:    K5G   84
  61:    RTN  
  64: L1:
  64:  DATAW #x00000050
  68: L3:
  68:  DATAW #x0000DFDF
  72:  DATAW #x6174730B
  76:  DATAW #x20207472
  80:  DATAW #x20202020
// Entry to:   start      
  84: L8:
  84:    LLL  L10
  86:    SP3  
  87:     L0  
  88:    SP4  
  89:    XCH  
  90:   RVP4  
  91:    SP5  
  92:   JEQ0  L12
  94: L11:
  94:    LP5  
  95:     LF  L2
  97:     K6  
  98:     L1  
  99:    AP4  
 100:    SP4  
 101:    LP3  
 102:   RVP4  
 103:    SP5  
 104:   JNE0  L11
 106: L12:
 106:     L0  
 107:    RTN  
 108: L10:
 108:  DATAW #x00000001
 112:  DATAW #x00000003
 116:  DATAW #x00000005
 120:  DATAW #x00000007
 124:  DATAW #x00000003
 128:  DATAW #x00000007
 132:  DATAW #x0000000B
 136:  DATAW #x0000000F
 140:  DATAW #x00000005
 144:  DATAW #x0000000B
 148:  DATAW #x00000011
 152:  DATAW #x00000017
 156:  DATAW #x00000003
 160:  DATAW #x00000003
 164:  DATAW #x00000000
 168: L9:
 168:  DATAW #x00000000
 172:  DATAW #x00000001
 176:  DATAW #x00000054
 180:  DATAW #x00000054
Code size =   184 bytes of 32-bit little ender Cintcode

It’s not the easiest code in the world to decipher, but if anyone wants to, I’ll annotate a few sections…

-Gordon

1 Like

Did someone say APL? I’m just a novice and this is very clunky. Anyone know how to print the rows while iterating over the SEQ array without needing an explicit loop?

I programmed this in TOPS-20 APLSF, then ported to Dyalog to display the APL characters.

      ∇XMASTR[⎕]∇
[0]   XMASTR WIDTH;SEQ;I
[1]  ⍝ XMASTR - VINTAGE COMPUTING CHRISTMAS CHALLENGE 2021
[2]  ⍝          PRINT XMAS TREE CENTERED FOR SCREEN OF <WIDTH>
[3]  ⍝          2021 DAVID MEYER <PAPA AT SDF.ORG>
[4]  ⍝ SEQ - NUMBER OF STARS FOR EACH ROW OF TREE
[5]  ⍝ I - CURRENT ROW INDEX
[6]   SEQ←(¯1+2×⍳4),(¯1+4×⍳4),(¯1+6×⍳4),3,3
[7]   I←1
[8]  LOOP:→(I>⍴SEQ)/END
[9]  ⍝ (⌊(W-N)÷2) IS NUMBER OF PREFIX SPACE CHARS TO CENTER
[10] ⍝ STRING OF <N> CHARS ON LINE OF <W> CHARS
[11]  ((⌊(WIDTH-SEQ[I])÷2)⍴' '),SEQ[I]⍴'*'
[12]  I←I+1
[13]  →LOOP
[14] END:
      XMASTR 80
                                       *
                                      ***
                                     *****
                                    *******
                                      ***
                                    *******
                                  ***********
                                ***************
                                     *****
                                  ***********
                               *****************
                            ***********************
                                      ***
                                      ***
3 Likes

Pygmy Forth on FreeDOS:

80 CONSTANT WIDTH
VARIABLE X
: FILLER ( N - ) WIDTH SWAP - 2 / SPACES ;
: ROW ( N - ) DUP FILLER FOR 42 EMIT NEXT CR ;
: XMASTR ( - )
  CR
  3 FOR
    8 I 1 + 2 * - X !
    4 FOR
      4 I -
      X @ * 1 - ROW
    NEXT
  NEXT
  3 ROW 3 ROW
;
2 Likes

It looks like assigning to quad might be the way:

      ⎕←2 4⍴'WINEMART'

Or, possibly, doing that mid-line:

If appears to the left of the symbol, it causes the result so far to be displayed. This may not be the result of evaluating the complete line as can occur anywhere on the line. The data is output together with a newline (carriage return) character

1 Like

I learned a few more tricks. Here’s a more APL-ish solution without a loop, though it uses a lot more memory, and I haven’t been able to get it to run on TOPS-20. (This was coded in Dyalog on my PC.)

It considers the display as an array of characters, and creates a series of arrays to store the display row and column of each cell, as well as the number of stars and the first and last columns of printed stars on each cell’s row. Finally, a map for printing stars is generated by comparing each cell’s column with the first and last star columns for the cell’s row.

      ∇xmast2[⎕]∇
[0]   xmast2 width;height;cells;celrow;celcol;nstars;first;last
[1]   height←14
[2]   cells←⍳height×width
[3]   celrow←⌈cells÷width
[4]   celcol←1+width|cells-1
[5]   nstars←¯1+(2×1+⌊(celrow-1)÷4)×1+4|celrow-1
[6]   nstars←((¯2×width)↓nstars),(2×width)⍴3
[7]   first←⌈(80-nstars)÷2
[8]   last←first+nstars-1
[9]   ⎕UCS height width⍴32+10×(celcol≥first)∧celcol≤last
      xmast2 80
                                       *                                        
                                      ***                                       
                                     *****                                      
                                    *******                                     
                                      ***                                       
                                    *******                                     
                                  ***********                                   
                                ***************                                 
                                     *****                                      
                                  ***********                                   
                               *****************                                
                            ***********************                             
                                      ***                                       
                                      ***                                       

(I see the video review of competition entries has begun, as a livestream

)

Back 2 B!

main() {
  extrn T;
  auto i,s,o;
  i = -1;
  while(o=T[++i]) {
    s=11-o/2;
    while(s--) putchar(' ');
    while(o--) putchar('*');
    putchar('*n');
  }
}
T[14] 1,3,5,7,3,7,11,15,5,11,17,23,3,3,0;

(W)interactive at TIO.

I tried it in SIMH’s PDP7 with Unix-V0 first, but wasn’t patient (or caffeinated?) enough to bear its ed, so I took the easier shortcut with ybc.

2 Likes

Nice to see B - ybc mentioned previously in this thread.

2 Likes

since we’re still playing (and why not!) I re-did my BCPL one in RTB Basic (which is my own version of Basic, written in C, runs under Linux)

It covers all bases this time…

// VC3 2021
//    Gordon Henderson - RTB Basic

print "Data/Table driven..."
print

data  1,3,5,7, 3,7,11,15, 5,11,17,23, 3,3, 0

read numCones
while numCones <> 0 cycle
  spaces = (tWidth - numCones) / 2
  proc lineOfCones (spaces, numCones)
  read numCones
repeat

print
print "Algorithm driven..."
print

for section = 1 to 3 cycle
  for branch = 1 to 4 cycle
    numCones = 2 * section * branch - 1
    spaces   = (twidth - numCones) / 2
    proc lineOfCones (spaces, numCones)
  repeat
repeat

for base = 1 to 2 cycle
  numCones = 3
  spaces   = (twidth - numCones) / 2
  proc lineOfCones (spaces, numCones)
repeat

print
print "Done."
end

def proc lineOfCones (s, c)
  proc many (s, " ")
  proc many (c, "*")
  print
endproc


def proc many (n, thing$)
  while n > 0 cycle
    print thing$;
    n = n - 1
  repeat
endproc

Image of the run:

Cheers,

-Gordon

2 Likes

And just to get this completely out of my system (!!!) some years ago when I was into Pi stuff, I wrote a CESIL interpreter in my RTB Basic - which would normally be somewhat boring however I added a ‘tree’ command in to it with some “lights” that could be “lit up” via a CESIL program…

This is a link to my old blog post in 2012…

CESIL Controlled Christmas Tree

The tree:

Cheers,

-Gordon

3 Likes

FORTRAN-20 on TOPS-20

@type xmastr.for
c xmastr - Vintage Computing Christmas Challenge 2021
c          Print Xmas tree centered on screen
c          2021 David Meyer <[email protected]> +JMJ

      program xmastr
      parameter nwidth = 80, nrows = 14
      character*23 cstars
      character*40 cspaces
      cstars = '***********************'
      cspaces = '                                        '
      do 1000 irow = 1, nrows
        istars = nrowstars (irow)
        ifill = (nwidth - istars) / 2
        write (5,10) cspaces(1:ifill)//cstars(1:istars)
10      format (1x,a)
1000  continue
      stop
      end


c nrowstars - Return number os stars to print on row <nrow>

      function nrowstars (nrow)
      if (nrow.gt.12) then
        nrowstars = 3
      else
        nrowstars = 2 * (1 + (nrow-1)/4) * (1 + mod(nrow-1,4)) - 1
      end if
      return
      end
@exec xmastr
LINK:   Loading
[LNKXCT XMASTR execution]
                                       *
                                      ***
                                     *****
                                    *******
                                      ***
                                    *******
                                  ***********
                                ***************
                                     *****
                                  ***********
                               *****************
                            ***********************
                                      ***
                                      ***
CPU time 0.01   Elapsed time 0.00
@

3 Likes

REAL PROGRAMS ARE PUNCHED ON CARDS :slight_smile:
What version of FORTRAN are you using?
How does modern FORTRAN handle program
data that come on punched cards after the FORTAN
SOURCE deck?
Ben.
NOTICES FORTRAN-20 ON TOPS-20 AFTER POSTING.

2 Likes

Nice to see another algorithmic approach!

1 Like

One of my first experiences of programming was at a Summer camp during Junior High in the late 1970s with FORTRAN on punch cards.Video terminals were for wimpy BASIC programmers. :wink:

1 Like

It’s not obvious, but that algorithm is lifted from my second APL version.

1 Like

Didn’t quite get down to JGH’s 78 characters, but this is a non-algorithmic BBC BASIC version in 79 characters:

1A$="LKJIKIGEJGDAKK":F.I=1TO14:S=ASC(M.A$,I,1))-64:P.SPC(S);STRI.25-2*S,"*"):N.

C64 BASIC can be pretty small, despite the lack of STRING$():

1a$="lkjikigejgdakk":fori=1to14:s=asc(mid$(a$,i,1))-64:?spc(s);:forj=1to25-2*s
2?"*";:next:?:next

Turns out encoding for the spaces and calculating the number of asterisks makes for slightly shorter code than vice versa. I’m sure I could write something truly incomprehensible in PostScript or Perl, but I don’t want to unleash the Old High Ones again …

1 Like

“Ph’nglui mglw’nafh Perl R’lyeh wgah’nagl fhtagn.”

for($r=1;$r<15;++$r){$s=$r<13?2*(1+int(($r-1)/4))*(1+($r-1)%4)-1:3;print ' 'x((79-$s)/2),'*'x$s,"\n";}

(102 bytes)

scruss’s encoding approach is fascinating the way it stores an integer array in the form of a character string. Here’s the Perl version:

$a='lkjikigejgdakk';for($i=0;$i<14;++$i){$s=ord(substr($a,$i,1))-69;print ' 'x$s,'*'x(79-2*$s),"\n";}

(101 bytes)

3 Likes

Obfuscated C

#include <stdio.h>
int main(){int r,s,c;for(r=1;r<15;++r){s=r>12?3:2*(1+(r-1)/4)*(1+(r-1)%4)-1;for(c=0;c<(79-s)/2;++c)printf(" ");for(c=0;c<s;++c)printf("*");printf("\n");}return 0;}

(185 bytes)

1 Like

Okayyy then … Perl, 74 characters, and remarkably easy to understand, too:

print map{" "x$_."*"x(25-2*$_)."\n"}map{ord()-64}split //,"LKJIKIGEJGDAKK"

Best explained backwards:

  • split //,"LKJIKIGEJGDAKK" returns a list of characters: “L”, “K”, “J”, …
  • map{ord()-64} transforms the list from characters to integers based on their ASCII code (ord()) less 64: 12, 11, 10, …
  • map{" "x$_."*"x(25-2*$_)."\n"} converts those numbers (via the $_ default variable) into a string of that number of spaces, plus that-number-massaged-a-bit number of asterisks, plus a newline.

If I were a good Perl programmer, I’d make the source look like something related to the output. I’m merely a mediocre one, though.

Sadly, my attempt to paste the program written using Perl’s Acme::Bleach was foiled by Markdown. Let’s just say it works just like Wile E. Coyote might expect it would …

1 Like

asc() shouldn’t care if you leave off the ,1 (for what it’s worth, which is only two bytes).

2 Likes