La sfida della Stella di Natale

Si è da poco conclusa la Vintage Computing Christmas Challenge 2022 (VC³ 2022), un simpatico concorso di programmazione organizzato da Logiker per il periodo di Natale.

L’obiettivo della sfida principale, chiamata Christmas Star Challenge, consiste nella realizzazione di un programma per qualsiasi computer e linguaggio (preferibilmente per sistemi vintage), in grado di rappresentare fedelmente la figura mostrata nell’immagine seguente, ottimizzando il codice il più possibile, oppure di migliorarla.

Immagine da realizzare per la Christmas Star Challenge
Immagine da realizzare per la Christmas Star Challenge (fonte: Logiker).

In alternativa, optando per la challenge Wild, era possibile creare un programma completamente differente, purché a tema natalizio.

Centinaia di persone si sono cimentate con la sfida e tutti i programmi in gara sono presentati nel video realizzato dall’organizzatore:

Video dei Logiker con i risultati della sfida e presentazione di tutti i programmi in concorso.

La mia implementazione della Stella di Natale in Tiny BASIC

Ho deciso di partecipare alla Christmas Star Challenge realizzando un programma in Tiny BASIC. La stella, che occupa una superficie quadrata il cui lato misura 17 caratteri, può essere suddivisa in quattro triangoli sovrapposti:

01    *            
02    **           
03    ***          
04    ****         
05    *****        
06    ******       
07    *******      
08    ********     
09    *********    
10    **********   
11    ***********  
12    ************ 
13    *************
14
15
16
17
01            *    
02           **    
03          ***    
04         ****    
05        *****    
06       ******    
07      *******    
08     ********    
09    *********    
10   **********    
11  ***********    
12 ************    
13*************    
14
15
16
17
01
02
03
04
05*************    
06 ************    
07  ***********    
08   **********    
09    *********    
10     ********    
11      *******    
12       ******    
13        *****    
14         ****    
15          ***    
16           **    
17            *    
01
02
03
04
05    *************
06    ************ 
07    ***********  
08    **********   
09    *********    
10    ********     
11    *******      
12    ******       
13    *****        
14    ****         
15    ***          
16    **           
17    *            

L’idea è quindi quella di iterare su ciascuna delle 17*17 posizioni e di stampare un carattere “*” se il “punto” considerato appartiene ad almeno uno dei 4 triangoli, altrimenti uno spazio vuoto ” “:

 100 LET R=0
 110 LET C=0
 120 LET S=0
 130 IF R<13 THEN IF C>3 THEN IF C<R+5 THEN LET S=1
 140 IF R<13 THEN IF C<13 THEN IF C>11-R THEN LET S=1
 150 IF R>3 THEN IF C<13 THEN IF C>R-5 THEN LET S=1
 160 IF R>3 THEN IF C>3 THEN IF C<21-R THEN LET S=1
 800 IF S=0 THEN PRINT " ";
 810 IF S=1 THEN PRINT "*";
 900 LET C=C+1
 910 IF C<17 THEN GOTO 120
 915 PRINT
 920 LET R=R+1
 930 IF R<17 THEN GOTO 110
1000 END

Rimuovendo gli spazi superflui e sfruttando le abbreviazioni delle istruzioni Tiny BASIC, è stato possibile ridurre la dimensione del listato del programma a 203 caratteri:

1R=0
2C=0
3S=0
4IFR<13IFC>3IFC<R+5S=1
5IFR<13IFC<13IFC>11-RS=1
6IFR>3IFC<13IFC>R-5S=1
7IFR>3IFC>3IFC<21-RS=1
8IFS=0PR" ";
9IFS=1PR"*";
10C=C+1
11IFC<17GOTO3
12PR
13R=R+1
14IFR<17GOTO2
15END

Ed ecco l’output:

    *       *    
    **     **    
    ***   ***    
    **** ****    
*****************
 *************** 
  *************  
   ***********   
    *********    
   ***********   
  *************  
 *************** 
*****************
    **** ****    
    ***   ***    
    **     **    
    *       *    

Non ho trovato un modo per ottimizzare ulteriormente il programma prima della fine della sfida; accetto comunque eventuali suggerimenti a riguardo!

Puoi osservare il programma in esecuzione su un computer Cosmac ELF emulato con Emma 02 nel seguente video, oppure eseguirlo e/o modificarne il codice utilizzando l’interprete online TinyBASICBlazor.

La mia implementazione in Tiny BASIC della Stella di Natale, in (lenta) esecuzione su Cosmac ELF, emulato con Emma 02.
La mia implementazione in Tiny BASIC della Stella di Natale, in esecuzione su TinyBASICBlazor, interprete Tiny BASIC per browser web.

Varianti ed evoluzioni

Data la semplicità della sintassi Tiny BASIC, che può essere considerato come un sottoinsieme della maggior parte dei dialetti BASIC disponibili, il programma può essere eseguito su una vastità di piattaform senza alcuna modifica (ad es. BBC Basic) o con modifiche minime. Ad esempio, su Sinclair ZX81 è sufficiente rimuovere l’istruzione “END” o sostituirla con “STOP” per avere una sintassi corretta.

Christmas Star - programma in esecuzione in BBC BASIC for SDL
La mia implementazione della Stella di Natale in esecuzione in BBC BASIC for SDL.

Proprio per il piccolo computer Sinclair, ho provato a compattare ulteriormente il codice del mio programma Tiny BASIC originale, anche se per ottenere risultati migliori in termini di dimensioni sarebbe stato necessario riscriverlo completamente sfruttando le caratteristiche del BASIC Sinclair.

Christmas Star - listato del programma per ZX81
Listato del programma per Sinclair ZX81.
Christmas Star - output del programma per ZX81
Output del programma per ZX81.
Programma per ZX81 in azione.

Infine, dato che lo scopo principale della competizione era quello di divertirsi, ho realizzato una versione Teletext della Stella di Natale, che riprende l’immagine di riferimento della sfida:

Christmas Star - versione Teletext
La Stella di Natale, versione Teletext.

La classifica ordinata per dimensione del codice sorgente è disponibile, insieme ai download di tutte le entry, su demozoo.org. Complimenti all’impareggiabile Dr. BEEP, che si è aggiudicato le prime posizioni con le versioni in Assembly per ZX81 e ZX Spectrum, il cui codice occupa solamente 27 e 29 byte rispettivamente!

Read in English

Successione di Fibonacci in Tiny BASIC

Ho appena aggiunto un nuovo programmino di esempio a TinyBASICBlazor, il mio ambiente web Tiny BASIC interattivo sperimentale: si tratta del classico calcolo della successione di Fibonacci.

Il programma è una versione semplificata (l’implementazione originale determina anche se gli elementi della successione siano numeri primi) e adattata per Tiny BASIC dell’esempio 4.18 del libro Programmare in BASIC (seconda edizione) di Byron S. Gottfried:

01  REM BASED ON EXAMPLE 4.18 FROM PROGRAMMING WITH BASIC BOOK BY BYRON S. GOTTFRIED
02  REM ADAPTED TO TINY BASIC BY MARCO'S RETROBITS
03  REM HTTPS://RETROBITS.ALTERVISTA.ORG    (ENGLISH)
04  REM HTTPS://SOMEBITSOFME.ALTERVISTA.ORG (ITALIAN)
05  REM HTTPS://RETROBITS.ITCH.IO
10  REM GENERATION OF FIBONACCI NUMBERS
20  PRINT "N= (3<=N<=23)";
30  INPUT N
35  IF N < 3 THEN GOTO 20
36  IF N > 23 THEN GOTO 20
40  PRINT
50  PRINT "GENERATION OF FIBONACCI NUMBERS"
60  PRINT
70  LET G=1
80  LET H=1
90  PRINT "I= ";1,"F= ";1
100 PRINT "I= ";2,"F= ";1
110 LET I=3
120   LET F=G+H
200   PRINT "I= ";I,"F= ";F
210   LET H=G
220   LET G=F
230 LET I=I+1
235 IF I<=N THEN GOTO 120
240 END

Nel listato è evidente l’assenza del ciclo FOR, sostituito da meno eleganti IF e GOTO. Inoltre, la serie generata è limitata a un massimo di 23 elementi a causa della precisione limitata (16 bit) del tipo di dato numerico in questa implementazione dell’interprete.

Riporto di seguito l’output della generazione dei primi 20 numeri di Fibonacci:

N= (3<=N<=23)? 20

GENERATION OF FIBONACCI NUMBERS

I= 1    F= 1
I= 2    F= 1
I= 3    F= 2
I= 4    F= 3
I= 5    F= 5
I= 6    F= 8
I= 7    F= 13
I= 8    F= 21
I= 9    F= 34
I= 10   F= 55
I= 11   F= 89
I= 12   F= 144
I= 13   F= 233
I= 14   F= 377
I= 15   F= 610
I= 16   F= 987
I= 17   F= 1597
I= 18   F= 2584
I= 19   F= 4181
I= 20   F= 6765
:

Ho deciso di aggiungere questo programma per puro sentimento nostalgico, in quanto mi ricorda con piacere le esercitazioni di informatica ai tempi della scuola, tanti anni fa.

Puoi eseguire il programma “Fibonacci” in TinyBASICBlazor semplicementa navigando a questo indirizzo: retrobits.altervista.org/tinybasicblazor?p=fibonacci.

Versione in Inglese di: Successione di Fibonacci in Tiny BASIC

Mele, pere e forza bruta in Tiny BASIC

Alcuni giorni fa, mi sono imbattuto in un post, pubblicato sul gruppo facebook dedicato al linguaggio di programmazione BASIC, in cui si fa riferimento a una challenge indetta sul forum della community di Liberty BASIC. L’obiettivo della sfida consiste nella realizzazione di un programma per risolvere il seguente “rompicapo” matematico:

C'è una cassetta di mele e pere.
Alcune sono grandi, altre piccole; alcune sono gialle, le altre sono verdi.
Non ci sono pere piccole né mele piccole e verdi.
Sono resi noti alcuni numeri: 25 mele, 17 pere, 32 frutti grandi, 28 gialli.
Ci sono due mele verdi in più rispetto alle pere verdi.
Trova il numero di mele grandi gialle.

Il problema è riconducibile a un sistema lineare di 5 equazioni in 5 incognite, per la cui risoluzione sono disponibili strumenti matematici ben noti (forse ne ho anche implementato qualcuno, quando ero studente), ma in questo caso ho deciso di divertirmi un po’ implementando in Tiny BASIC un algoritmo di forza bruta per verificare tutte le soluzioni teoricamente possibili, fino a che si trova quella effettivamente corretta. Il listato del programma è riportato di seguito:

1 REM ********************
2 REM * APPLES AND PEARS *
3 REM ********************
4 REM BRUTE FORCE TINYBASIC IMPLEMENTATION
5 REM BY MARCO'S RETROBITS
6 REM RETROBITS.ALTERVISTA.ORG
7 REM PLEASE TAKE A SEAT, THIS COULD BE SLOW
8 REM ********************
10 REM THERE WAS A BOX OF APPLES AND PEARS
11 REM SOME ARE BIG, SOME ARE SMALL;
12 REM SOME ARE YELLOW, REST ARE GREEN
13 REM THERE ARE NO SMALL PEARS
14 REM AND NO SMALL GREEN APPLES.
15 REM SOME NUMBERS ARE GIVEN:
16 REM 25 APPLES, 17 PEARS
17 REM 32 BIG FRUITS
18 REM 28 YELLOW ONES.
19 REM THERE ARE TWO MORE GREEN APPLES THAN GREEN PEARS.
20 REM FIND THE NUMBER OF BIG YELLOW APPLES.
30 REM C: SMALL YELLOW APPLES
40 REM D: BIG YELLOW APPLES
50 REM E: BIG GREEN APPLES
60 REM F: BIG YELLOW PEARS
70 REM G: BIG GREEN PEARS
80 REM A: APPLES; P: PEARS
90 REM B: BIG FRUITS; Y: YELLOW ONES
100 LET A = 25
110 LET P = 17
120 LET B = 32
130 LET Y = 28
200 REM FOR C = 1 TO A
201 LET C=1
210   REM FOR D = 1 TO A-C
211   LET D = 1
220     REM FOR E = 1 TO A-C-D
221     LET E = 1
230       REM FOR F = 1 TO P
231       LET F = 1
240         REM FOR G = 1 TO P-F
241         LET G = 1
250           GOSUB 2000
260           IF S = 0 THEN GOTO 460
270           PRINT "SOLVED!"
280           PRINT "SMALL YELLOW APPLES:", C
290           PRINT "BIG YELLOW APPLES:", D, "*"
300           PRINT "BIG GREEN APPLES:", E
310           PRINT "BIG YELLOW PEARS:", F
320           PRINT "BIG GREEN PEARS:", G
400           END
460         REM NEXT G
461         LET G = G+1
462         IF G <= P-F THEN GOTO 250
470       REM NEXT F
471       LET F = F+1
472       IF F <= P THEN GOTO 240
480     REM NEXT E
481     LET E = E+1
482     IF E <= A-C-D THEN GOTO 230 
490   REM NEXT D
491   LET D = D+1
492   IF D <= A-C THEN GOTO 220
500 REM NEXT C
501 LET C = C+1
502 IF C <= A THEN GOTO 210
510 PRINT "NO SOLUTION!"
520 END
1990 REM ** CHECK ROUTINE **
2000 LET S = 0
2001 REM PRINT C, D, E, F, G
2010 REM 25 APPLES, 17 PEARS
2020 IF C + D + E <> A THEN RETURN
2030 IF F + G <> P THEN RETURN
2040 REM 32 BIG FRUITS
2050 IF D + E + F + G <> B THEN RETURN
2060 REM 28 YELLOW ONES
2070 IF C + D + F <> Y THEN RETURN
2080 REM THERE ARE TWO MORE GREEN APPLES THAN GREEN PEARS
2090 IF E <> G + 2 THEN RETURN
2100 REM ** SOLVED! **
2110 LET S = 1
2990 RETURN

Ogni volta che ho a che fare con Tiny BASIC, inizialmente mi stupisco del fatto che questo dialetto non preveda i cicli FOR…NEXT. Questo in realtà non è un grosso problema, in quanto si può ovviare con le (meno eleganti) istruzioni di IF e GOTO. Un’altra limitazione è data dai nomi delle variabili, che possono essere costituiti da un’unica lettera maiuscola.

Ho eseguito il programma “Mele e Pere” su TinyBasicBlazor, l’ambiente TinyBASIC interattivo per web browser da me realizzato a partire da TinyBasic.NET e descritto in questo post. La soluzione ha richiesto più di mezz’ora (devo verificare il motivo), mentre con TinyBasic.NET in versione console, sono necessari pochi secondi.

Ah, quasi dimenticavo: ci sono 7 mele grandi e gialle!

SMALL YELLOW APPLES: 10
BIG YELLOW APPLES: 7 *
BIG GREEN APPLES: 8
BIG YELLOW PEARS: 11
BIG GREEN PEARS: 6
Read in English

MaN1cPuzzle in versione Tiny BASIC

Recentemente, mi sono divertito con la realizzazione di TinyBasicBlazor, un ambiente Tiny BASIC interattivo, basato sulla conversione in C# dell’interprete TinyBasic realizzato da Tom Pittman ed eseguito sui browser web grazie alla tecnologia WebAssembly.

Volendo aggiungere contenuti originali ai programmi di esempio già inclusi, ho deciso di convertire il mio MaN1cPuzzle, riscrivendolo in Tiny BASIC. MaN1cPuzzle è una generalizzazione del classico Gioco del 15, implementato originariamente per il computer ZX Spectrum in 20 linee di Sinclair BASIC. Il processo di coversione è stato tutto sommato semplice, a parte qualche minima difficoltà dovuta alle differenze tra i due dialetti del BASIC.

Screenshot di MaN1cPuzzle, versione ZX Spectrum
MaN1cPuzzle, versione ZX Spectrum

La differenza più evidente è che Tiny BASIC consente solo un’istruzione per riga. Di fatto questo non costituisce un problema, infatti, mentre sul MaN1cPuzzle originale ho sfruttato la possibilità di avere più istruzioni per linea per contenere il programma in 20 linee, con il porting a Tiny BASIC non ho dovuto soddisfare questo requisito. Quindi, ho approfittato di questa situazione per includere commenti esplicativi e rendere il codice più leggibile.
In secondo luogo, l’implementazione di Tiny BASIC di Tom Pittman non supporta i cicli FOR, introdotti con Tiny BASIC Extended. Tuttavia, questi possono essere facilmente sostituiti con istruzioni di GO TO, con buona pace dei puristi della programmazione strutturata, che non considerano i salti incondizionati una buona pratica (E. Dijkstra l’ha persino definita dannosa!).
Un’altra differenza sostanziale tra i dialetti è che Tiny BASIC supporta solo aritmetica a numeri interi. Tuttavia, anche se i numeri in virgola mobile potrebbero essere gestiti con una programmazione aggiuntiva, come descritto nel Tiny BASIC Experimenter’s Kit, non sono necessari in questo tipo di gioco.
Inoltre, Tiny BASIC non ha istruzioni per la grafica / i colori / il suono, ma per questo tipo di gioco è sufficiente l’output di testo con alcune pseudo grafiche realizzate con caratteri ASCII standard.

L’unico punto difficile del processo di porting è stata la mancanza del supporto agli array in Tiny BASIC. MaN1cPuzzle, infatti, utilizza un array bidimensionale per memorizzare le posizioni delle tessere nella griglia di gioco. Sono stato in grado di superare questo problema adottando l’approccio descritto in TIC-TAC-TOE IN TINY BASIC or How to Make a Program TINY di Tom Pittman, tramite le funzioni peek e poke, per leggere e scrivere il contenuto di posizioni contigue di memoria dall’indirizzo 0 all’indirizzo M * N-1 (dove M e N sono le dimensioni della griglia di gioco), simulando così un array. L’interprete Tiny BASIC, infatti, integra alcune routine che possono essere invocate con la funzione USR. In particolare, la funzione peek è disponibile all’indirizzo COLD_START + 20 e la funzione poke è disponibile all’indirizzo COLD_START + 24, essendo COLD_START uguale a 256 (100h) nell’implementazione dell’interprete utilizzata da TinyBasicBlazor.

Il risultato finale è mostrato nella figura sotto e il gioco è giocabile sul tuo browser web tramiteTinyBasicBlazor (è richiesta la tastiera). All’avvio, il programma richiede l’indirizzo COLD_START; inserisci semplicemente 256. Quindi il programma richiede le dimensioni della griglia e il numero di spostamenti casuali da utilizzare per il mescolamento iniziale della griglia. Ho previsto due shortcut che consentono l’avvio immediato del gioco, per giocare con 15 tessere su una griglia 4 × 4 o con 24 tessere su una griglia 5 × 5.
È disponibile anche il listato BASIC del gioco.

Screenshot di MaN1cPuzzle, versione Tiny BASIC
MaN1cPuzzle, versione Tiny BASIC, in esecuzione su web browser con TinyBasicBlazor

Link e riferimenti

Read in English

Un interprete Tiny BASIC sul tuo web browser!

Periodicamente, il mio interesse è catturato dagli interpreti BASIC, presenti su praticamente tutti i computer hobbistici e domestici a partire dalla metà degli anni ’70 ed in particolar modo negli anni ’80.
Tra i vari dialetti del BASIC, Tiny BASIC ricopre sicuramente un ruolo molto importante.
Tiny BASIC è stato ideato tra il 1975 e il 1976 e il suo sviluppo come alternativa aperta rispetto al costoso BASIC di Microsoft fu incentivato dalla controvèrsia sulla pirateria informatica, innescata dalla distribuzione non autorizzata di copie dello stesso, denunciata da Bill Gates nella sua Lettera aperta agli hobbisti.
Gli interpreti Tiny BASIC furono rilasciati gratuitamente o commercializzati a basso costo; tra questi, il più famoso è l’interprete implementato da Tom Pittman (Itty Bitty Computers) mediante macchina virtuale, alla cui storia Steven Levy ha dedicato un capitolo del suo Hackers: Gli eroi della rivoluzione informatica. Nel 2006, Tom Pittman rilasciò una versione aggiornata del suo interprete, riscritta in linguaggio C e successivamente Mohan Embar ne effettuò il porting in Java, C# e Flex/Actionscript.

Negli ultimi anni, la tecnologia WebAssembly (Wasm) si sta affermando come standard per lo sviluppo di applicazioni web performanti, realizzate in altri linguaggi oltre a Javascript.
In particolare, appena un mese fa, Microsoft ha rilasciato ufficialmente Blazor WebAssembly, ambiente basato su WebAssembly che consente l’esecuzione di codice .NET direttamente nel browser, senza necessità di installare alcun plugin aggiuntivo.

Lavorando quotidianamente con C#, il rilascio di Blazor WebAssembly ha destato il mio interesse e così ho deciso di coniugare il desiderio di approfondire questa nuova tecnologia con la passione per il retrocomputing, realizzando un ambiente Tiny BASIC contenuto in una pagina web ed eseguito sul browser. Blazor WebAssembly mi ha permesso di includere l’interprete di Mohan Embar senza alcuna modifica al codice sorgente e di realizzare una semplice console per l’I/O e i componenti per caricare ed eseguire alcuni programmi BASIC predefiniti, o altri programmi eventualmente presenti sul proprio computer.


Il risultato di questo progetto è TinyBasicBlazor, il cui codice sorgente è disponibile su GitHub. Per completare l’opera, ho iniziato la conversione di MaN1cPuzzle (versione del Gioco del 15 originariamente implementata in 20 linee di BASIC per ZX Spectrum) in Tiny BASIC e spero di includerla presto tra i programmi di esempio.

Con TinyBasicBlazor, puoi programmare come nel 1976 (ma su un browser moderno)!

Read in English