100 porte, diversi linguaggi – 1

mj1

Un esercizio per far pratica con Racket e confrontarlo con altri linguaggi. Sono ancora nuovo, chissà se…

Intanto non è una cosa mia, al solito copio; da Rosetta Code. Trovate tutto qui: 100 doors. Per continuare mi sa che dovete leggere l’intro di là.
Il problema è semplice e –secondo me– di quelli che si devono risolvere con carta + matita (2B) + gomma; volendo è possibile tenere accesa la radio ma spegnere il telefono e chiudere il Browser (ma le mails?). Poi si deve scrivere la documentazione, compresa la soluzione. E il programma risulterà semplicissimo, anzi manco serve; quello che Rosetta definisce versione ottimizzata.

Ovviamente in questo post interessa solo la versione non ottimizzata, quella che non si deve fare in pratica 😉

AWK

Gli scripts di AWK di solito sono piccoli, non in questo caso:

BEGIN {
  for(i=1; i <= 100; i++)
  {
    doors[i] = 0 # close the doors
  }
  for(i=1; i <= 100; i++)
  {
    for(j=i; j <= 100; j += i)
    {
      doors[j] = (doors[j]+1) % 2
    }
  }
  for(i=1; i <= 100; i++)
  {
    print i, doors[i] ? "open" : "close"
  }
}

d0
Sì, l’output è disastroso, forse si può migliorare;

BEGIN {
  for(i=1; i <= 100; i++)
  {
    doors[i] = 0 # close the doors
  }
  for(i=1; i <= 100; i++)
  {
    for(j=i; j <= 100; j += i)
    {
      doors[j] = (doors[j]+1) % 2
    }
  }
  for(i=1; i <= 100; i++)
  {
    printf ("%3d : %s    ", i, doors[i] ? "open " : "close")
    if (i % 5 == 0) printf ("\n")
  }
}

d1

Fortran

OK, non si usa più ma chissà…

PROGRAM DOORS
 
  INTEGER, PARAMETER :: n = 100    ! Number of doors
  INTEGER :: i, j
  LOGICAL :: door(n) = .TRUE.      ! Initially closed
 
  DO i = 1, n
    DO j = i, n, i
      door(j) = .NOT. door(j)
    END DO
  END DO 
 
  DO i = 1, n
    WRITE(*,"(A,I3,A)", ADVANCE="NO") "Door ", i, " is "
    IF (door(i)) THEN
      WRITE(*,"(A)") "closed"
    ELSE
      WRITE(*,"(A)") "open"
    END IF
  END DO
 
END PROGRAM DOORS

d2Anche qui si potrebbe modificare l’output, lasciato come esercizio.
Tutti i fortrainers sanno che non c’è distinzione tra maiuscole e minuscole (tranne nei literals); qui vengono abusate le maiuscole. Se consideriamo che il ciclo (il for) qui si chiama DO il programma è leggibilissimo (secondo me).
Anticamente, quando si usavano le schede perforate, c’era una rigorosa suddivisione delle colonne. Adesso non più, non sempre, per cui ho dovuto specificare l’opzione per il free format.
Ah! ‘nticamente (pre Fortran 77) si sarebbe scritto in modo molto diverso, ma non voglio andare troppo OT.
Ancora: è quasi come il Basic, o è solo una mia impressione?

Haskell

La versione Haskell (che non riporto) m’intriga, parecchio. Chissà che… Peccato che ci sono Racket, Python et al. 🙄

Hy

Hy è speciale, roba di PaulTag, ne ho parlato in passato. E da allora il progetto è cresciuto, mi sa che… (forse).

(def doors (* [False] 100))
 
(for [pass (range (len doors))]
  (for [i (range pass (len doors) (inc pass))]
    (assoc doors i (not (get doors i)))))
 
(for [i (range (len doors))]
  (print (.format "Door {} is {}."
    (inc i)
    (if (get doors i) "open" "closed"))))

d3

newLISP

Una delle mie passioni da sempre, ecco:
OOPS! 😳 errore, avevo inizialemente pubblicato la versione ottimizzata, aggiornato.

(set 'Doors (array 100))  ;; Default value: nil (Closed)
 
(for (x 0 99)
    (for (y x 99 (+ 1 x))
        (setf (Doors y) (not (Doors y)))))
 
(for (x 0 99)  ;; Display open doors
    (if (Doors x)
        (println (+ x 1) " : Open")))
        
(exit)

d4

Ho fatto un paio di modifiche.

newLISP è diverso sia da Common Lisp sia da Scheme, una cosa tutta a se; funziona e per cose piccole rockz! 😀

Octave

La versione freeware di MatLab.

doors = false(100,1);

for i = 1:100
  for j = i:i:100
    doors(j) = !doors(j);
  endfor
endfor

for i = 1:100
  if ( doors(i) )
    printf("%d open\n", i);
  endif
endfor

d5
Anche qui ho modificato l’output, anzi di più. Effettivamente è semplice, la ragione per cui piace a tanti (o sono solo i miei contatti?).

Perl

Adesso c’è la versione 6, cambia parecchio ma io continuo con la 5. Anche qui modificato parecchio.

my @doors;
for my $pass (1 .. 100) {
    for (1 .. 100) {
        if (0 == $_ % $pass) {
            $doors[$_] = not $doors[$_];
        };
    };
};
 
for (1 .. 100) { 
    print "Door ", $_, " is open\n" if ($doors[$_]);
};

d6

Python

Modificato per l’output e per la versione 3 dove range ha sostituito xrange e print è una funzione, quindi le parentesi.

doors = [False] * 100 
for i in range(100):
    for j in range(i, 100, i+1):
        doors[j] = not doors[j]
    if doors[i]:
        print("Door %d:" % (i+1), "is open")

d7

Racket

Uno dei motivi di questo post.

#lang racket

;; Applies fun to every step-th element of seq, leaving the others unchanged.
(define (map-step fun step seq)
  (for/list ([elt seq] [i (in-naturals)])
    ((if (zero? (modulo i step)) fun values) elt))) 
(define (toggle-nth n seq)
  (map-step not n seq))
 
(define (solve seq)
  (for/fold ([result seq]) ([_ seq] [pass (in-naturals 1)])
    (toggle-nth pass result)))
 
(for ([door (solve (make-vector 101 #f))] [index (in-naturals)]
      #:when (and door (> index 0)))
  (printf "~a is open~%" index))

d8
Uhmmm… alquanto lispico 🙄 Da riparlarne.
Aggiornamento: il codice è stato corretto, ne mancava una parte, la definizione di map-step.

Maxima

In realtà c’era un altro motivo per questo post: Maxima.
Qui sono niubbassay, anzi di più. Per cui metto solo lo screenshot di Maxima Algebra System

d9

Ma mi piace molto più –sono vecchio– Xmaxima, ecco la console:

d10

A questo punto ci vorrebbe la discussione e le conclusioni. Solo che il post diventa troppo lungo, non si può o almeno non conviene. Rimando a prossimamente, mica finisce qui 😉

:mrgreen:

Posta un commento o usa questo indirizzo per il trackback.

Trackback

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo di WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione /  Modifica )

Google photo

Stai commentando usando il tuo account Google. Chiudi sessione /  Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione /  Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione /  Modifica )

Connessione a %s...

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.

%d blogger hanno fatto clic su Mi Piace per questo: