Archivi Categorie: Uncategorized

Octave – Errori e warnings – III – 55


Continuo da qui finendo il capitolo errori, qui.

Gestire i warnings

Like an error, a warning is issued when something unexpected happens. Unlike an error, a warning doesn’t abort the currently running program. A simple example of a warning is when a number is divided by zero. In this case Octave will issue a warning and assign the value Inf to the result.


Passo qui.

Segnalare un warning
It is possible to issue warnings from any code using the warning function. In its most simple form, the warning function takes a string describing the warning as its input argument. As an example, the following code controls if the variable ‘a’ is non-negative, and if not issues a warning and sets ‘a’ to zero.


Since warnings aren’t fatal to a running program, it is not possible to catch a warning using the try statement or something similar. It is however possible to access the last warning as a string using the lastwarn function.

It is also possible to assign an identification string to a warning. If a warning has such an ID the user can enable and disable this warning as will be described in the next section. To assign an ID to a warning, simply call warning with two string arguments, where the first is the identification string, and the second is the actual warning. Note that warning IDs are in the format “NAMESPACE:WARNING-NAME”. The namespace “Octave” is used for Octave’s own warnings. Any other string is available as a namespace for user’s own warnings.

Built-in Function: warning (template, ...)
Built-in Function: warning (id, template, ...)
Built-in Function: warning ("on", id)
Built-in Function: warning ("off", id)
Built-in Function: warning ("query", id)
Built-in Function: warning ("error", id)
Built-in Function: warning (state, "backtrace")
Built-in Function: warning (state, id, "local")

Display a warning message or control the behavior of Octave’s warning system.
Format the optional arguments under the control of the template string template using the same rules as the printf family of functions and print the resulting message on the stderr stream. The message is prefixed by the character string ‘warning: ’. You should use this function when you want to notify the user of an unusual condition, but only when it makes sense for your program to go on.

The optional message identifier allows users to enable or disable warnings tagged by id. A message identifier is of the form “NAMESPACE:WARNING-NAME“. Octave’s own warnings use the “Octave” namespace (see XREFwarning_ids). The special identifier "all" may be used to set the state of all warnings.

If the first argument is "on" or "off", set the state of a particular warning using the identifier id. If the first argument is "query", query the state of this warning instead. If the identifier is omitted, a value of "all" is assumed. If you set the state of a warning to "error", the warning named by id is handled as if it were an error instead. So, for example, the following handles all warnings as errors:

warning ("error");

If the state is "on" or "off" and the third argument is "backtrace", then a stack trace is printed along with the warning message when warnings occur inside function calls. This option is enabled by default.

If the state is "on", "off", or "error" and the third argument is "local", then the warning state will be set temporarily, until the end of the current function. Changes to warning states that are set locally affect the current function and all functions called from the current scope. The previous warning state is restored on return from the current function. The "local" option is ignored if used in the top-level workspace.

Implementation Note: For compatibility with MATLAB, escape sequences in template (e.g., “\n" => newline) are processed regardless of whether template has been defined with single quotes, as long as there are two or more input arguments. To disable escape sequence expansion use a second backslash before the sequence (e.g., “\\n“) or use the regexptranslate function.

Built-in Function: [msg, msgid] = lastwarn ()
Built-in Function: lastwarn (msg)
Built-in Function: lastwarn (msg, msgid)

Query or set the last warning message.
When called without input arguments, return the last warning message and message identifier.
With one argument, set the last warning message to msg.
With two arguments, also set the last message identifier.

The functions distributed with Octave can issue one of the following warnings. Non la riporto, è lunga, inutile (quasi) e poi c’è di là dovesse servire.

Avanti, qui.

Abilitare e disabilitare i warnings
The warning function also allows you to control which warnings are actually printed to the screen. If the warning function is called with a string argument that is either "on" or "off" all warnings will be enabled or disabled.
It is also possible to enable and disable individual warnings through their string identifications. Example:


Nota perso: io appartengo alla scuola che errori e, in misura minore) warnings vanno presi con molta considerazione. E corretti senza proseguire l’elaborazione.
Aneddoto fine anni ’70: il programma per la soluzione di telai che usavamo a volte abortiva con un messaggio incomprensibile. La prassi era quella di cancellare il file temporaneo T$0000, controllare i dati di input e rilanciare il programma. Quando ho provato a chiarire il messaggio di errore ho scoperto che il file temporaneo conteneva il dato errato. Resta il mystero mysteryouso a tutt’oggi perché il programmatore avesse voluto scrivere su file invece che a video e non l’avesse scritto sul manuale d’uso 😳


Octave – istruzioni I – 41


Proseguendo da qui oggi sono qui.


Statements may be a simple constant expression or a complicated list of nested loops and conditional statements.
Control statements such as if, while, and so on control the flow of execution in Octave programs. All the control statements start with special keywords such as if and while, to distinguish them from simple expressions. Many control statements contain other statements; for example, the if statement contains another statement which may or may not be executed.
Each control statement has a corresponding end statement that marks the end of the control statement. For example, the keyword endif marks the end of an if statement, and endwhile marks the end of a while statement. You can use the keyword end anywhere a more specific end keyword is expected, but using the more specific keywords is preferred because if you use them, Octave is able to provide better diagnostics for mismatched or missing end tokens.
The list of statements contained between keywords like if or while and the corresponding end statement is called the body of a control statement.

Da qui si passa in dettaglio, un’istruzione alla volta, inizio da qui.

L’istruzione if
The if statement is Octave’s decision-making statement. There are three basic forms of an if statement. In its simplest form, it looks like this:

if (condition)

condition is an expression that controls what the rest of the statement will do. The then-body is executed only if condition is true.

The condition in an if statement is considered true if its value is nonzero, and false if its value is zero. If the value of the conditional expression in an if statement is a vector or a matrix, it is considered true only if it is non-empty and all of the elements are nonzero. The conceptually equivalent code when condition is a matrix is shown below.

if (matrix) ≡ if (all (matrix(:)))

The second form of an if statement looks like this:

if (condition)

If condition is true, then-body is executed; otherwise, else-body is executed.
Here is an example:


Il punto-virgola credo sia opzionale (correggerò se del caso).

The third and most general form of the if statement allows multiple decisions to be combined in a single statement. It looks like this:

if (condition)
elseif (condition)

Any number of elseif clauses may appear. Each condition is tested in turn, and if one is found to be true, its corresponding body is executed. If none of the conditions are true and the else clause is present, its body is executed. Only one else clause may appear, and it must be the last part of the statement.

In the following example, if the first condition is true (that is, the value of x is divisible by 2), then the first printf statement is executed. If it is false, then the second condition is tested, and if it is true (that is, the value of x is divisible by 3), then the second printf statement is executed. Otherwise, the third printf statement is performed.


Note that the elseif keyword must not be spelled else if, as is allowed in Fortran. If it is, the space between the else and if will tell Octave to treat this as a new if statement within another if statement’s else clause. For example, if you write

if (c1)
else if (c2)

Octave will expect additional input to complete the first if statement. If you are using Octave interactively, it will continue to prompt you for additional input. If Octave is reading this input from a file, it may complain about missing or mismatched end statements, or, if you have not used the more specific end statements (endif, endfor, etc.), it may simply produce incorrect results, without producing any warning messages.

It is much easier to see the error if we rewrite the statements above like this,

if (c1)
  if (c2)

using the indentation to show how Octave groups the statements.

Pronto a passare qui.

L’istruzione switch
It is very common to take different actions depending on the value of one variable. This is possible using the if statement in the following way

if (X == 1)
  do_something ();
elseif (X == 2)
  do_something_else ();
  do_something_completely_different ();

This kind of code can however be very cumbersome to both write and maintain. To overcome this problem Octave supports the switch statement. Using this statement, the above example becomes

switch (X)
  case 1
    do_something ();
  case 2
    do_something_else ();
    do_something_completely_different ();

This code makes the repetitive structure of the problem more explicit, making the code easier to read, and hence maintain. Also, if the variable X should change its name, only one line would need changing compared to one line per case when if statements are used.

The general form of the switch statement is

switch (expression)
  case label
  case label


where label can be any expression. However, duplicate label values are not detected, and only the command_list corresponding to the first match will be executed. For the switch statement to be meaningful at least one case label command_list clause must be present, while the otherwise command_list clause is optional.

If label is a cell array the corresponding command_list is executed if any of the elements of the cell array match expression. Example:


As with all other specific end keywords, endswitch may be replaced by end, but you can get better diagnostics if you use the specific forms.

One advantage of using the switch statement compared to using if statements is that the labels can be strings. If an if statement is used it is not possible to write

if (X == "a string") # This is NOT valid

since a character-to-character comparison between X and the string will be made instead of evaluating if the strings are equal. This special-case is handled by the switch statement, and it is possible to write programs that look like this

switch (X)
  case "a string"

Non di stretto interesse (per me) ma c’è differenza rispetto al C (il case inclusivo e quindi il break), come raccontato qui.


Javascript – Strumenti di lavoro

Anzitutto una piccola parentesi per quei pochissimi che non hanno mai provato ad eseguire javascript. Gli strumenti minimi necessari sono un browser ed un editor di testi. Personalemente uso un paio di browser come eredità dei tempi andati quando i due browser maggiori (Internet Explorer e Firefox) si guardavano in cagnesco e quando meno te lo aspettavi un codice perfetto su uno dei due, inaspettatemente, sull’altro aveva effetti fantasiosi. Ora i due non possono più chiamarsi “maggiori” perché superati dall’ultimo arrivato Chrome di Google e, per fortuna, sembra che hanno messo fine alle ostilità allineandosi quasi perfettamente allo standard della W3C, rendendo inutili i vecchi script per il riconoscimento del browser.

Qual è il migliore editor di testi? Ovvio, quello che conoscete meglio. Io uso Textpad da troppi anni e la voglia di imparare nuove cose si è molto affievolita. Un editor molto diffuso ed apprezzato e gratuito, cosa che non guasta mai, è Notepad++.

Un accenno a Brackets, un editor open source per diversi linguaggi (HTML, CSS e JavaScript) su cui l’Adobe sta lavorando e dalle caratteristiche interessanti (completamento automatico del codice HTML e CSS, suggerimenti e chi più ne ha più ne metta). Io l’ho provato prima con un js estremamente grosso (più di 50000 righe di codice) e Brackets non riesce a portare a termine il caricamento. Poi ho provato js più accettabili e al termine del caricamento vengono segnalati errori incomprensibili; segno di un’immaturità del programma. Vedremo in futuro se manterrà le promesse.

Accanto agli editor tradizionali vi sono anche ambienti di sviluppo integrati, come Eclipse e Visual Studio che, con un apposito plugin, permettono di gestire javascript. Entrambi sono gratuiti.

Con il normale editor di testi bisogna, anzitutto, scrivere uno scheletro di pagina HTML:

<!DOCTYPE html>
< script>

// qui va messo il codice javascript


(Nota: è stato aggiunto uno spazio dopo il segno di minore e prima di script solo per motivi “tipografici”, altrimenti WordPress avrebbe cancellato tutto il tag)
Il codice precedente è perfetto per l’HTML5. Con l’HTML4 la prima riga era un mezzo papier e anche nel tag script bisognava specificare il tipo di script (type=”text/javascript”), che ora non è obbligatorio, o anche, nelle versioni più vecchie, il linguaggio (language=”JavaScript”, attualmente obsoleto). Il linguaggio poteva essere diverso, forse nelle speranze di coloro che hanno ideato l’html. In questo momento probabilmente il javascript è diventato il linguaggio “per eccellenza”, indispensabile se si vuole fare pagine web non troppo banali.

Per la mia pigrizia, poiché non voglio passare la vita a scrivere cose inutili, utilizzo anche Dreamweaver, che è un editor HTML per Windows e per Apple. Infatti tutta quella roba là sopra viene scritta automaticamente appena si crea la pagina web. Poi, per eseguire il codice, si preme il tasto F12 con cui viene richiamato il browser di default.

In mancanaza di Dreamweaver (che costa un pacco di soldi) o di altro strumento ci arrangiamo come possiamo. Scriviamo quindi il primo facilissimo script (Kernighan & Ritchie insegnano):

alert(“Hello world!”);


e lo mettiamo là, al posto dei puntini, all’interno del tag script:

<!DOCTYPE html>
< script>
alert(“Hello world”);

Poi salviamo il tutto con il nome, ad esempio, Hello.htm (o quello che vi pare, basta che il nome del file abbia estensione HTM o HTML). Magari cerchiamo di salvare il file in una certella facilmente raggiungibile, così non ci dobbiamo rovinare la giornata per ritrovare dove abbiamo salvato il nostro lavoro. Anche il desktop va bene (provvisoriamente, perché è proprio brutto vedere il desktop pieno di tutte quelle icone, di solito inutili, che non sappiamo nemmeno da dove scappano fuori). Infine clicchiamo due volte sull’icona di Hello.htm e… voilà… ecco apparire una finestrella (popup modale) con scritto l’ormai usuale saluto.

Non succede niente? Evidentemente si è verificato un qualche errore di battitura.
Già, ma quale? Dobbiamo fare una ricerca da certosini, misurare la lunghezza della virgola per essere sicuri di non averla confusa col punto? Per fortuna i browser hanno i loro bravi strumenti di debugger. In particolare la Console. Con Firefox si apre il menù Strumenti -> Sviluppo web -> Console web e troveremo l’indicazione della prima istruzione che il browser non riesce ad interpretare. Con Internet Explorer si accede alla Console con premendo il tasto F12. Anche con Chrome si può accedere alla Console tramite menù (More Tools -> Javascript Console). A questo punto dobbiamo solo correggere il sorgente e riprovare.


Rust – il linguaggio – 35


Da qui copiando /usr/local/share/doc/rust/html/book/unsized-types.html.

Tipi senza dimensione

Most types have a particular size, in bytes, that is knowable at compile time. For example, an i32 is thirty-two bits big, or four bytes. However, there are some types which are useful to express, but do not have a defined size. These are called ‘unsized’ or ‘dynamically sized’ types. One example is [T]. This type represents a certain number of T in sequence. But we don’t know how many there are, so the size is not known.

Rust understands a few of these types, but they have some restrictions. There are three:

  • We can only manipulate an instance of an unsized type via a pointer. An &[T] works just fine, but a [T] does not.
  • Variables and arguments cannot have dynamically sized types.
  • Only the last field in a struct may have a dynamically sized type; the other fields must not. Enum variants must not have dynamically sized types as data.

So why bother? Well, because [T] can only be used behind a pointer, if we didn’t have language support for unsized types, it would be impossible to write this:

fn main() {
    impl Foo for str {
        // ...


fn main() {
    impl Foo for [T] {
        // ...


Instead, you would have to write:

impl Foo for &str {

Meaning, this implementation would only work for references, and not other types of pointers. With the impl for str, all pointers, including (at some point, there are some bugs to fix first) user-defined custom smart pointers, can use this impl.

Nota: ottengo ancora un errore perché il codice è incompleto, ma dovrebbe andare 🙄


If you want to write a function that accepts a dynamically sized type, you can use the special bound, ?Sized:

struct Foo<T: ?Sized> {
    f: T,

This ?, read as “T may be Sized”, means that this bound is special: it lets us match more kinds, not less. It’s almost like every T implicitly has T: Sized, and the ? undoes this default.
Servirebbe un esempio completo, chissà se in futuro… 🙄


Marvin Minsky – un po’ di cinguettii

Twitter è il mio social media preferito; pare abbia difficoltà a emergere | crescere | soppravcivere, peccato e davvero non capisco perché.
Ecco qualche link su Marvin Minsky, ce ne sono tanti, mi limito a due tweeps particolarmente attivi sull’argomento.

Rainer Joswig:


E poi Luis Souto Graña: Marvin Minsky declara: “tipado dinamista hasta la sepultura”.
Non è Twitter ma c’è anche questo: Hacker koan, Uncarved_block.


Marvin Minsky

Non ho parole, riporto quelle di altri:


Analisi del 2015

I folletti delle statistiche di hanno preparato un rapporto annuale 2015 per questo blog.

Ecco un estratto:

Il Madison Square Garden può accogliere 20 000 spettatori per un concerto. Questo blog è stato visto circa 61.000 volte nel 2015. Se fosse un concerto al Madison Square Garden, ci vorrebbero circa 3 rappresentazioni esaurite perché lo vedessero altrettante persone.

Clicca qui per vedere il rapporto completo.

Questo è quello che ha scritto il signor WordPress.
Ma voglio aggiungere qualcosa anch’io, posso?  OK 😀
nel corso dell’anno sono cambiate parecchie cose, tante. Di qualcuna c’è traccia nel blog altre sono in background e –probabilmente– invisibili o quasi.
C’è stato un nuovo autore che ha fatto faville (non so se quest’espressione è dialettale o si capisce, spero di sì), è finita –praticamente– una mia collaborazione con amici che dava come sottoprodotto anche post (su Python, GnuPlot, Fortran, altro ancora), mi sono messo a frequentare il Lisp, anche nella sua ultima versione, Racket.
So benissimo che Racket non è un argomento mainstream, i miei post hanno pochissime visite ma mi piace e mi sa che continuerò. E non importa che nel 2015 ci siano state 62mila visite in calo rispetto alle 71mila dell’anno precedente.
Sono d’altronde combiate parecchie cose in tutta la blogosfera, scomparsi o trasformati alcuni a cui ero affezionato. Chissà …
E poi –perso ma devo dirlo– anche la salute non è più quella di una volta, niente di grave ma noioso assay 🙄
E la memoria, cos’è già che devo dire? …. Uh! sì, buon anno! 😀

Visto nel Web – 211

Forse mi sono sfuggite cose, non sono stato molto attento. Comunque ecco cosa ho visto nel Web.

convert a LibreOffice Calc/Excel stylesheet to .csv in command-line
::: The Ubuntu Incident

Numerical differentiation
::: John D. Cook

L’Europa degli open data: un mercato potenziale da 325 miliardi
::: il Sole 24 Ore

Loading a TensorFlow graph with the C++ API
::: Medium

Stopping WhatsApp Won’t Stop Terrorists
::: The New York Times


Whistleblowers: How NSA Created the ‘Largest Failure’ In Its History
::: Slashdot

L’equilibrio tra aspettative e realtà. Il senso critico. La strategia dell’innovazione. Dalla ricerca di consenso alle decisioni strutturali
::: Luca De Biase

My new book. Mi nuevo libro. Meu novo livro
di Kazimir Majorinc, aspettando la versione in inglese 😀
::: Google+

Stack Overflow and the Zeitgeist of Computer Programming
::: Slashdot

Looks like an interesting read. And it’s free
::: PurdonKyle


Racket v6.3
::: Racket

The End of Dynamic Languages
::: Elben Shira

Dell Accused of Installing ‘Superfish-Like’ Rogue Certificates On Laptops
::: Slashdot ::: SIAMO GEEK

Il digitale secondo Renzi, Luna e me
non tutto condivisibile ma in gran parte OK
::: Sotto Un Cielo di Bit

Le 3 paure paralizzanti che non ci fanno aprire un blog
::: Sergio Gridelli


Yahoo Denies Ad-blocking Users Access To Email
ha un sacco di pubblicità noiosa, certo che blocca l’antiblock
::: Slashdot

Estimating the exponent of discrete power law data
troppo specifico? ma dimostra ancora una volta che con Python (e JD Cook) si può 😀
::: John D. Cook

Questo sollevato da @stefanoepifani è un problema importante
::: fabiochiusi

Programmare Arduino con Scratch
::: Prometheus Now

Racket’s new macro expander is awesome
::: disnet

not even once

‘Any sentence that starts with, “It would be neat if Racket could ___”
::: d_run

The Storage Engine: A Timeline of Milestones in Storage Technology
::: Computer History Museum

These two links explore the doubts I had yesterday about using exceptions
::: volothamp

“You wrote this Python tool I’m using. Can you debug my spaghetti code for me?”
::: jakevdp

In first half of 2015, 72% of Twitter removal requests from government agencies came from Turkish authorities
::: ForbesTech


A programmer wrote scripts to secretly automate a lot of his job — and email his wife and make a latte
::: Business Insider

What Is the Future of the Television?
::: Slashdot

Parole a caso. Tanto per fare audience.
::: carolafrediani

Raspberry Pi Zero: the $5 computer
::: Raspberry Pi ::: mntmn ::: daw985 ::: Engadget ::: Raspberry_Pi ::: burriko ::: BGR


Scikit Flow
This is a simplified interface for TensorFlow, to get people started on predictive analytics and data mining
::: google

Long Tutorial
(Racket) This tutorial is derived from a week-long Redex summer school, run July 27–31, 2015 at the University of Utah.
::: Racket

Non è questione di privacy
::: Il Post

The Downfall of Imperative Programming
vecchio ma richiamato ultimamente
::: FP Complete

Google received 348,085 total right to be forgotten requests (42% lead to removed links)
::: fabiochiusi


Parses panic stack traces, densifies and deduplicates goroutines with similar stack traces. Helps debugging crashes and deadlocks in heavily parallelized process.
::: maruel

Static vs. Dynamic Languages: A Literature Review
::: Lambda the Ultimate

Free Pascal Compiler 3.0.0 Is Out; Adds Support For 16-Bit MS-DOS, 64-Bit iOS
l’evoluzione del Turbo Pascal; quasi-quasi…
::: Slashdot

Il Giglio magico della cybersecurity
::: gabriella_roux

New research shows websites, social media and smartphone usage are the key priorities for creating public value
::: Museums and the Web


LSD Microdosing Gaining Popularity For Silicon Valley Professionals
::: Slashdot

SeaMonkey ./build start
::: OS)(SIDE

Do you know how much your computer can do in a second?
io ho sbagliato parecchio
::: Julia Evans

LiFi internet: First real-world usage boasts speed 100 times faster than WiFi
::: IBTimes

Mi accorgo che continuavo a usare il nome vecchio (The Endeavour) per il blog di John D. Cook, corretto.

Molto più bravi di me con il foglio di calcolo

programmer_joke12Io su Facebook sono alquanto atipico. Lo uso solo per spammare, nel senso che segnalo quando faccio un post sui blog. E poco più. Rispondo a chi mi tagga (si dice così, vero?) e ogni tanto ci do una scorsa ma senza né impegno né metodo. Ho anche smesso di fare gli auguri di compleanno, mi sembra una cosa non da orso quale vorrei essere, o almeno sembrare.
Poi capitano cose che mi fanno dire “Ohhh!” proprio come quel testa-di-povia di Povia.

Sto parlando di questo post trovato sul gruppo Figli di Archimede, legittimi e…in adozione che non so bene se si riesca a vedere da chi non ne fa parte.

In particolare mi riferisco al post del 19 maggio 2015 di Cristiano Armellini che riproduco (se del caso cancello quanto mi verrà chiesto):

questo file Excel non l’ho fatto io ma lo propongo perché ha una formula molto interessante per ottenere i numeri primi (nulla di particolare ma minimizza lo spazio di memoria).

Problema adesso: non so se posso mettere il link al foglio di calcolo, cioè l’ho messo ma non so se funziona e allora metto un paio di immagini per ricostruirlo (tipo Ikea, anzi ricetta per libro di cucina (tipo ricettario)).


Come si vede nella colonna B si trovano i numeri naturali (per qualche motivo la serie parte dalla riga 2, forse per poter mettere un titolo alle colonne). La colonna C invece ha una formula, a partire dalla riga 3; quella che in B3 ha il testo 2.

Le formule con questo tipo di strumento sono un po’ –come dire– facciamo che metto quella per la cella C6, quella in cui mi trovo nell’immagine precedente:


Chiaro no? L’unica cosa particolare è RESTO che è quello che di solito si chiama modulo e viene scritto % o mod(), questo dice l’help:


Quindi tornando alla formula io la trovo che mi meraviglia, assay.

Per scriverla basta posizionarsi in C3 e scrivere:

=SE(SOMMA(SE(RESTO(B3;B$2:B2)=0; 1; 0))=1; 1; "")

Poi copiarla e incollarla su tutte le celle sottostanti e gli indici vengono aggiornati automaticamente (tranne quelli bloccati con il $); per esempio in C6 abbiamo quella della figura là sopra, questa:

=SE(SOMMA(SE(RESTO(B6;B$2:B5)=0; 1; 0))=1; 1; "")

Per capire cosa fa, proprio come nel Lisp (anche qui le parentesi abbondano) si riduce partendo dalla coppia di parentesi più interne e si procede verso l’esterno e il tutto diventa chiaro. Se la somma del valore della lambda per il calcolo del modulo per il numero nella colonna a sinistra rispetto a tutti i numeri precedenti (partendo dal 2) è zero il numero è primo e viene scritto 1 nella cella.

OK? 😀

Ecco io ho usato lambda, parola che non credo si trovi nei manuali di queste cose ma è quella. Anche perché RESTO da solo farebbe un’altra cosa.
Quello che mi fa poviare è com’è scritta la formula, la sua sinteticità; con i linguaggi normali (tranne APL e successori) sarebbe parecchio più lunga. Ma resta comprensibile, l’ho capita anch’io.

Poi che io ci riesca a scriverla è un altro discorso, completamente differente. Anche perché, se del caso, ho altre possibilità. Esempio:


Oppure, installando bsdgames:


Ma se fossi invidioso l’invidia per gli excelsers rimarrebbe tutta :mrgreen:

Tirare i dadi

Qualche giorno fa su un (poco) noto social, il buon Zar poneva una questione apparentemente semplice.

“Ci sono cinque dadi a sei facce recanti (le facce) i seguenti numeri: 0, 0, 1, 2, 3, 4. Si lanciano tutti insieme e si fa la somma dei valori ottenuti. Problema: calcolare le probabilità di uscita dei numeri da 0 a 20.”

Nel post linkato Zar fa la trattazione matematica, e vi consiglio di leggerlo tutto perché merita. Nel “socialino dell’ammmore” abbiamo anche discusso alcune soluzioni al problema tramite programmini in vari linguaggi di programmazione. Io, che nel frattempo mi sono parecchio arrugginito con Haskell, ne ho approfittato per proporre 2 soluzioni con questo elegante linguaggio di programmazione: la prima semplice semplice, la seconda una generalizzazione della prima. Dato che le soluzioni le avevo messe su pastebin e chissà che fine faranno, adesso le riposto qui, così magari viene voglia anche a voi di provare nel vostro linguaggio di programmazione preferito.

Cominciamo con la prima:

module Main where
import System.Environment

main :: IO ()
main = do args <- getArgs          
          putStrLn("Probabilità di " ++
                   (args !! 0) ++ " con 5 dadi : " ++ " = " ++ 
                   show( prob_dadi (read (args!!0)::Integer) 5 ))
          -- putStrLn("Test : " ++ show(test))

prob_faccia :: Integer -> Rational               
prob_faccia 0 = 2/6
prob_faccia 1 = 1/6
prob_faccia 2 = 1/6
prob_faccia 3 = 1/6
prob_faccia 4 = 1/6
prob_faccia n = 0
prob_dadi :: Integer -> Integer -> Rational
prob_dadi n 0 | n == 0   = 1
              | n > 0    = 0
              | n < 0    = 0
prob_dadi n nd  =  (prob_faccia 0)  *  (prob_dadi n (nd-1)) + 
                   (prob_faccia 1)  *  (prob_dadi (n-1) (nd-1)) +
                   (prob_faccia 2)  *  (prob_dadi (n-2) (nd-1)) +  
                   (prob_faccia 3)  *  (prob_dadi (n-3) (nd-1)) +
                   (prob_faccia 4)  *  (prob_dadi (n-4) (nd-1))

test = (test_loop 20)

test_loop (-1) = 0
test_loop n = (prob_dadi n 5) + test_loop (n-1)

Il programmino prende sulla linea di comando il numero di cui si vuole calcolare la probabilità (tra 5 e 20 ovviamente) e restituisce la probabilità in forma di frazione. La funzione principale è prob_dadi che naturalmente è ricorsiva. Il primo parametro n è il numero di cui si vuole calcolare la probabilità, il secondo è il numero di dadi da lanciare.

Per ottenere n, si lancia un dado e:
– si calcola la probabilità che venga 1, e si moltiplica per la probabilità che i restanti nd-1 dadi ottengano n-1;
– si calcola la probabilità che venga 2, e si moltiplica per la probabilità che i restanti nd-1 dadi ottengano il numero n-2
– ecc.
Tutte queste probabilità si sommano per ottenere la probabilità finale.
Resta da stabilire la fine della ricorsione: la probabilità di ottenere n > 0 con 0 dadi, è sempre 0; la probabilità di ottenere n == 0 con 0 dadi è pari a 1.

E’ chiaro? Spero di si. Se avete capito questo programmino, potrete agevolmente capire il secondo programmino che generalizza il contenuto delle facce mettendolo in una lista.
Ecco il codice (ATTENZIONE: per mia praticità, e per confondervi un po’ le idee, qui ho scambiato l’ordine dei parametri della prob_dadi! adesso prende prima il numero dei dadi e poi il numero da ottenere):

module Main where
import System.Environment

main :: IO ()
main = do args <- getArgs          
          putStrLn("Probabilità di " ++
                   (args !! 0) ++ " con 5 dadi : " ++ " = " ++ 
                   show( prob_dadi 5 (read (args!!0)::Integer)))
          -- putStrLn("Test : " ++ show(test))

facce :: [Integer]
facce = [0, 0, 1, 2, 3, 4]

prob_faccia :: Rational
prob_faccia = 1/6

prob_partial:: Integer -> Integer -> Integer -> Rational
prob_partial nd n faccia =  
  prob_faccia * (prob_dadi (nd-1) (n-faccia))

prob_dadi :: Integer -> Integer -> Rational             
prob_dadi 0 n | n == 0   = 1
              | n > 0    = 0
              | n < 0    = 0

prob_dadi nd n =
  sum (map (prob_partial nd n) facce)  

test = (test_loop 20)

test_loop (-1) = 0
test_loop n = (prob_dadi 5 n) + test_loop (n-1)

Qui prob_dadi fa una sommatoria (che nel programma precedente era svolta a mano, elemento per elemento) di una lista che risulta dall’applicazione (tramite map) della funzione prob_partial agli elementi della lista facce.

La funzione prob_partial fa la moltiplicazione di prima:
– calcola la probabilità di ottenere una certa faccia, e la moltiplica per la probabilità di ottenere il numero n-faccia con nd-1 dadi.

E adesso a voi! (Voglio la stessa cosa in Lisp, mi raccomando!)