Category Archives: Python

Ancora Wallis

bb9Ancora qualche considerazioni sul post relativo al prodotto di Wallis.
Intanto la sua inefficienza, per ottenere un approssimazione decente occorrono davvero tante iterazioni, ecco, con Python:

#!/usr/bin/python3

# calcolo di pi con la formula di Wallis

p = 1            
lsup = 1000 * 1000 * 100 + 1
stp = lsup // 10
for n in range(1, lsup):
    t = 4 * pow(n, 2.0)
    p = p * t /(t - 1)
    if n % stp == 0:
    	print(n, p, 2 * p)

w-py

46 secondi per 100 milioni di iterazioni :grin:

Ma molto più interessante che non servono; dopo i 40 milioni il risultato non migliora; Il numero di cifre previste per il float è stato raggiunto e fine. Vero è che anche con Python si potrebbe fare molto meglio, con NumPy/SciPy, per esempio.

Ma se invece provassimo con Racket, il mio linguaggio preferito (ce ne sono tanti altri pari merito –quasi)?
Racket non approssima, ha il tipo rational [/usr/racket/doc/guide/numbers.html] e quindi si può prevedere… Provo.

Adesso devo confessare una cosa personale: nei periodi in cui mi occupo di linguaggi di programmazione diversi le mie prestazioni diminuiscono fortemente. Ultimamente sono alle prese con Rust (molto interessante, grazie Robitex), Python (da sempre, sono tendenzialmente evangelista Python) e –almeno in questo momento– Racket. Ecco faccio confusione, non riesco a ragionare in termini funzionali. Il codice che segue è la traduzione dello script Python, non è bello, potrei fare di meglio, abuso di set!, cosa evitabile con let (e let*). Anzi a mia idea era quella, non è detto che in futuro… :wink:
Inoltre, per ragioni di tempo il numero delle iterazioni è ridotto, un solo milione. Ecco cosa ottengo

#lang racket                        ;; wallis
                                    ;; product 
(define (wallis)
  (define t 0)
  (define p 1)
  (for ([n (range 1 1000001)])      ;; 1M
    (set! t (* 4 n n))
    (set! p (/ (* p t) (- t 1)))
    (when (zero? (modulo n 100000)) ;; 100K
      (printf "~a ~a ~a \n"
              n (exact->inexact p)
              (exact->inexact (* 2 p))))))

(wallis)

Semplice vero? Uso la procedura exact->inexact per visualizzare i risultati altrimenti è il diluvio.

Alla partenza mi trovo in queste condizioni:

i

Sì, una delle CPU è subito riservata al task, poi si procede

i2

intanto attendo, attendo, attendo e infine:

fine2

Quasi 81 minuti! E non si è raggiunta l’approssimazione di Python. Bisognerebbe proseguire ancora. Ma la vita è troppo breve; e io sono in ritardo :roll:

Racket dev’essere preso per il suo verso. E roll over Beethoven Wallis (quasi-cit.) :grin:

:mrgreen:

Attenti al falso amico con Python

mama

Un mystero mysteryouso, assay. Anzi no ma a volte capita :roll:
Ecco una formula curiosa che si presta a fare un esercizio sui cicli.

wallis

È il prodotto di Wallis, qui la pagina della Wiki (la versione italiana c’è ma meno completa).
Ah! converge molto lentamente, vale solo per questo esercizio.
Sembra semplice :grin:
Il primo tentativo è disastroso:

#!/usr/bin/python3

# calcolo di pi con la formula di Wallis
#ERRATO!!!

p = 1
for n in range(1, 11):
	t = 4 * n^2
	e = t / (t - 1)
	p = p * e 
	print(n, e, p, 2 * p)
print(2.0 * p)

i
Correggo, ecco:

#!/usr/bin/python3

# calcolo di pi con la formula di Wallis

p = 1.0
for n in range(1, 11):
	t = 4 * pow(n, 2.0)
	e = t /(t - 1)
	p = p * e 
	print(n, e, p, 2 * p)
print(2.0 * p)

r
Dov’è l’errore?

pow

La risposta è che a volte ci lasciamo ingannare dai falsi amici, esaminiamo interattivamente:

int

Ecco! Capita non solo in linguistica!

Poi il falso amico multilingua (l’originale è olandese) che preferisco e quello dell’immagine lassù in cima :loll:
Attualmente in italiano funziona foneticamente.

OK, tornando a Python l’elevazione a potenza si fa con pow() o ** (ehi! come in Fortran :grin:):

int2

Invece ^ è un operatore bitwise: The ^ operator yields the bitwise XOR (exclusive OR) of its arguments, which must be integers.

Verifico, con l’aiuto di bin():
xorSemplice vero? restituisce i bits settati a 1 per entrambi i numeri.
Caso risolto :grin:

:mrgreen:

Fattori di un numero intero

bb3OK, sono indaffarato su altre cose ma non posso abbandonare Racket, il mio linguaggio di programmazione preferito (con zilioni di altri, tutti pari-merito).
E come già in passato (è piaciuto) un confronto con altri dei miei linguaggi preferiti. Poi prossimamente continua lo studio di Rust, anche lì si stanno accumulando robe: sono travolto dai ritardi :roll:

Sto copiando da Rosetta code, qui: Factors of an integer.

AWK

Comincio con un’eccezione: AWK non è multipiattaforma ma ci sono affezionato da sempre

#!/usr/bin/awk
BEGIN {
    print("enter a number or C/R to exit")
}
{   if ($0 == "") { exit(0) }
    if ($0 !~ /^[0-9]+$/) {
      printf("invalid: %s\n",$0)
      next
    }
    n = $0
    printf("factors of %s:",n)
    for (i=1; i<=n; i++) {
      if (n % i == 0) {
        printf(" %d",i)
      }
    }
    printf("\n")
}

f0Per passare il numero da fattorizzare sulla riga di comando si può fare:

#!/usr/bin/awk
{
    if ($0 == "") { exit(0) }
    if ($0 !~ /^[0-9]+$/) {
      printf("invalid: %s\n",$0)
      next
    }
    n = $0
    printf("factors of %s:",n)
    for (i=1; i<=n; i++) {
      if (n % i == 0) {
        printf(" %d",i)
      }
    }
    printf("\n")
}

f1E il comando si può –ovviamente semplificare:

#!/bin/bash
echo $1 | awk -f f1.awk

f2

Python

La versione più semplice è semplicissima:

#!/usr/bin/python3

def factors(n):
    return [i for i in range(1, n + 1) if not n%i]

print(42, ":", factors(42))
print(2701, ":", factors(2701))
print(32768, ":", factors(32767))

f3La prima ottimizzazione si ottiene considerando solo i numeri compresi nell’intervallo [1 .. n/2 + 1]. Notare // per la divisione fra interi (dalla versione 3). In questo caso il numero stesso non compare nell’output.

#!/usr/bin/python3

def factors(n):
    return [i for i in range(1, n // 2 + 1) if not n%i]

print(42, ":", factors(42))
print(2701, ":", factors(2701))
print(32768, ":", factors(32767))

f4Meglio ancora, i divisori non possono essere maggiori della radice quadrata del numero; output come il caso precedente (ho modificato il range del for facendolo partire da 2, con 1 il numero testato compare nell’output).

#!/usr/bin/python3

from math import sqrt

def factors(n):
    factors = set()
    for x in range(2, int(sqrt(n)) + 1):
        if n % x == 0:
            factors.add(x)
            factors.add(n // x)
    return sorted(factors)
      
print(42, ":", factors(42))
print(2701, ":", factors(2701))
print(32768, ":", factors(32767))

Quant’è efficace l’ottimizzazione? considero un numero grosso, 1323116819 e provo, modificando gli script che elaborino il primo parametro passato, così:

#!/usr/bin/python3

import sys

def factors(n):
    return [i for i in range(1, n + 1) if not n%i]

N = int(sys.argv[1])
print(N, ":", factors(N))

f5Eh, sì :grin:

Racket

La versione elementare:

#lang racket
 
;; a naive version
(define (naive-factors n)
  (for/list ([i (in-range 1 (add1 n))]
             #:when (zero? (modulo n i))) i))

(printf "~a : " 42)
(printf "~a \n" (naive-factors 42))

f6Molto meglio usando factorize per ricavare i primi e costruirne la lista:

#lang racket
 
(require math)
(define (factors n)
  (sort (for/fold ([l '(1)]) ([p (factorize n)])
          (append (for*/list ([e (in-range 1 (add1 (cadr p)))] [x l])
                    (* x (expt (car p) e)))
                  l))
        <))

(printf "~a : " 42)
(printf "~a \n" (factors 42))

 

Quanto è più veloce? Provo con lo stesso numero usato per Python:

#lang racket

;; a naive version
(define (naive-factors n)
  (for/list ([i (in-range 1 (add1 n))]
             #:when (zero? (modulo n i))) i))

(require math)
(define (factors n)
  (sort (for/fold ([l '(1)]) ([p (factorize n)])
          (append (for*/list ([e (in-range 1 (add1 (cadr p)))] [x l])
                    (* x (expt (car p) e)))
                  l))
        <))

(define N 1323116819)
(printf "naive version, ~a : " N)
(time (printf "~a \n" (naive-factors N)))
(printf "better version, ~a : " N)
(time (printf "~a \n" (factors N)))

f7Ma esiste un modo ancora migliore, usare la funzione divisors che fa la stessa cosa di factorize ma è più veloce. Uso il numero enorme di Rosetta.

f8

Anche sulle cose semplici c’è molto da imparare :roll:

:mrgreen:

Py-graphics ovvero: attenti al prof!

kk3Ho trovato un altro tweep che vi raccomando :grin:
E a dirla tutta sono stato pollo, ho letto il cinguettio, ho copiato il codice e l’ho lanciato. E pensare che lo dice chiaramente, è lento, assay, anzi di più. E bisogna leggere i commenti, Twitter è vivo e prestante (quando merita).
Comunque per puro masochismo lo rifaccio qui. Ma leggete tutto il post prima di lanciare l’esecuzione dello script.

Una cosa: il modulo graphics.py non è installato di default. Si può trovare qui, Python 3.x Resources; scaricare il file graphics.py.

Per fare le cose davvero per bene il file graphics.py si può spostare nella directory dei moduli di Python3:r0

sì sbagliato pwd :sad: sapete com’è…

Ed ecco, dice John di provare questo script (l’ho leggermente modificato):

from graphics import *
from random import *
from time import ctime
def go(win):
    for i in range(200000):
        x = randint(-250, 250)
        y = randint(-250, 250)
        c = "blue" #"green"
        if (x * x + y * y < 200 * 200):
            c = "red"
        win.plot(x, y, c)
        if i % 10000 == 0:
            print(i, ctime())

def main():
    seed()
    win = GraphWin("my stuff", 500, 500)
    win.setCoords(-250, - 250, 250, 250)
    go(win)
    print("\nDone, click to exit.")
    win.getMouse()
    win.close()
    
main()

r4

Disastroso, ecco:

r6

Python è bello, ma a volte … :sad:
Capita anche altrove, p.es. qui :wink:

:mrgreen:

Ancora su index_of

kk2Mi sa che ci sono stati un po’ di pasticci imprecisioni, incomprensioni, whatever :roll:

No sono davvero pasticci :evil: cose che capitano quando non ci si documenta a dovere

rtfm

Intanto lambda, funzione anonima come nel Lisp (e adesso molti altri linguaggi): sì c’è ma ha un limite: dev’essere formata da una sola istruzione quindi non è che va bene sempre.

Mi sembra illuminante questo post: Yet Another Lambda Tutorial.
Cosa che non serve più di tanto al nostro caso.
Ma index_of è quello che mi fa perdere un pakko di punti :sad: perché c’è built-in, quasi pronta:

i0

basta poco, testare se è nella lista:

i1

Quindi ecco la nuova funzione index_of:

def index_of (lst, item):
    if item in lst:
        return lst.index(item)
    else:
        return -1

#test
lst = ["alpha", "beta","gamma"]
print(index_of(lst, "beta"))
print(index_of(lst, "gamma"))
print(index_of(lst, "delta"))

i2

Una precisazione: la versione che torna una lista non è quella che serve nel caso (come il mio) in cui l’item è presente, se c’è, una volta sola; inoltre la list comprehension percorre sempre tutta la lista cosa dispendiosa per liste lunghe.

Chissà se impegnandomi sodo nel 2016 riuscirò a recuperare :roll: io ce la metto tutta e poi ho un aiuto, grazie J :grin:
:mrgreen:

index_of e get_nth di una lista in Python

oggi siamo ancora tutti più buoni; poi basta :grin:

oggi siamo ancora tutti più buoni; poi basta :grin:

Recentemente ho rimediato alla mancanza (sentita almeno da me) di due funzioni indispensabili in Racket, index-of e get-nth.

Siccome ne ho postato diverse versioni riporto quelle che considero definitive, almeno per adesso :lol:

(define (index-of lst ele)
  (for/or ([y lst] [i (in-naturals)] #:when (equal? ele y)) i))

(define (get-nth lst pos)
  (if (and (exact-nonnegative-integer? pos)
           (< pos (length lst)))
           (list-ref lst pos)
           "out-of-range"))

Adesso —serendipicatamente— mi sono trovato la necessità di usarle con Python, l’altro mio linguaggio di programmazione preferito (pari-merito con altri Nmila).

Chissà se si può fare?
Uhmmm…
:grin:

get_nth è automatica, quasi:

p0

manca la gestione del fuori range, provvedo:

def get_nth(lst, n):
	if n in range(len(lst)):
		return lst[n]
	else:
		return "out-of-range"

# test
lst = ["alpha", "beta", "gamma"]
print(get_nth(lst, 1))
print(get_nth(lst, 2))
print(get_nth(lst, 4))
print(get_nth(lst, -1))

p1

E index_of? ecco:

def index_of(lst, item):
	n = 0
	for x in lst:
		if x == item:
			return n
		n += 1
	return False

# test
lst = ["alpha", "beta", "gamma"]
print(index_of(lst, "beta"))
print(index_of(lst, "gamma"))
print(index_of(lst, "delta"))

p2

OK. Però poi un ripensamento, sapete com’è l’evilussione evoluzione che c’è anche nei linguaggi, la list comprehension, descritta in dettaglio p.es. qui e qui dove si valuta anche la sua convenienza rispetto al ciclo for.

In ogni caso ecco:

def index_of(lst, item):
	return [i for i, x in enumerate(lst) if x == item]
	
# test
lst = ["alpha", "beta", "gamma"]
print(index_of(lst, "beta"))
print(index_of(lst, "gamma"))
print(index_of(lst, "delta"))

p3

OK. Sì, ritorna una lista, in the pythonic way.

:mrgreen:

Una keyword che manca in Python

x0Ultimamente sono alle prese con Racket, l’ultima evoluzione del Lisp ma sono anche tentato da Haskell e in ogni caso continuo con Python. Ebbene sì, lo raccomando, quasi sempre :grin:
Recentemente ho dovuto modificare uno script di quelli che nascono al volo per un caso specifico, lunghi poche righe ma poi con il tempo crescono con il rischio di ingarbugliarsi da far invidia a brainfuck.
Non parlo di come si può evitare questo degrado stilistico, cose che si sanno (e a volte si mettono anche in pratica) ma di una caratteristica di Python: l’assenza dell’istruzione case (Pascal, Delphi) detta anche switch (C) e cond (Lisp) e … (OK, ha parecchi nomi).

In Python si usa if:

ifA parte l’estrosità di scrivere elif al posto di elseif o else if funziona. E siccome c’è solo quella si usa, e funziona benissimo.

Ma perché manca case? Visto che siamo quasi in periodo di feste (auguri, nèh!) e questo genere di post piacciono quasi-quasi interrogo il Web sull’argomento.

Parto da un documento ufficiale PEP 3103 — A Switch/Case Statement.
Dice in sintesi Guido che è ripetitiva, inefficiente, non ci guadagni niente, non rende il codice più chiaro, insomma: A quick poll during my keynote presentation at PyCon 2007 shows this proposal has no popular support. I therefore reject it.

Non tutti sono d’accordo, per esempio texasman1979: I wrote a Python Switch statement. Uhmmm… è stato giudicato non chiaro e unphytonic. Chiuso. Anche se vedi dopo.

L’argomento è sentito, ecco un altro post simile, questa volta pythonic (sembra): Michael Schneider, Replacements for switch statement in Python?
E la soluzione che io conto di mettere per ultima me la stanno spoilerando tutti :roll:

Una ricetta diversa, C-istica viene proposta da Brian Beck: Readable switch construction without lambdas or dictionaries.
Riceve parecchi commenti, tra i quali “A very inventive approach!!! This is what I’d call an inspired solution. Of all switch-case substitutes, I probably like this one most“.

Più teorico l’articolo di Lance Finn Helsten, Python Switch Statement, ricco di notizie storiche, bello :grin:

OK, A questo punto mi sembra di aver messo parecchia carne al fuoco. Restano due questioni in sospeso:

  • cosa ho fatto per il caso cui accennavo all’inizio: ho aggiunto un elif, dovevo solo fare manutenzione dello script e me la sono cavata con pochissime rihe di codice;
  • in generale se dovesse capitare in futuro come mi comporterei? Non ne sono sicuro ma probabilmente i dizionari, sono la via, come descritti nel post lasciato qui in fondo. Ma forse ha ragione teh BDFL, come sempre (kwasy).

L’ultima parola spetta a PyDanny, Daniel Roy Greenfeld, tra le altre cose a fantasy novel author e former NASA python coder: Why Doesn’t Python Have Switch/Case? Tutto da leggere.
E se continua a mancarvi il case là c’è la soluzione :grin:

:mrgreen:

Un aiuto per i comandi Bash

11988Aggiornamento: corretto errore nella riga 12 dello script.
Un post che è solo un esercizio; ho visto che il precedente su un argomento simile è piaciuto allora ecco.
Si tratta di Bash, anche se lo script è in Python, versione 3, quella da usare sempre tranne casi particolari (p.es. WxPython non c’è ancora; ci sarà mai?).

Esiste una reference per Bash ottima, qui: Bash Reference Manual.
Potrebbe essere comodo poterla consultare in locale, ecco come.

Ho salvato in locale il file con il nome BRM.html e posso fare qualcosa come

b0

La parola cercata —printf— compare 12 volte ma il risultato è pasticciato e serve a poco. Notare però che l’ultimo hit ha un link:

<a href="#index-printf"><code>printf</code>

È un link interno (ovviamente) che voglio visualizzare con il nome assoluto, l’URL.
Con Python, usando una pipe è semplice, meno di 30 righe di codice, eccolo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/usr/bin/python3

import subprocess
import sys, os

if len(sys.argv) != 2:
	print('cosa cerco?')
	exit(2)

dirp = os.path.abspath(os.path.dirname(sys.argv[0]))
cerco = sys.argv[1]
command = 'grep -i ' + cerco + ' ' + dirp + '/BRM.html' 
prefisso = 'file://' + dirp + '/BRM.html'

proc = subprocess.Popen(command, shell=True, 
		stdout=subprocess.PIPE, 
		stderr=subprocess.PIPE)
proc.wait()
outp = str(proc.stdout.read())

ps = outp.find('<a href="#')
while ps >= 0:
	pe = outp.find('">', ps)
	trovato = outp[ps+9 : pe]
	if cerco in trovato:
		print(prefisso + trovato)
	ps = outp.find('<a href="#', pe)

Lo script è semplice, comunque:

la riga 10 dirp = os.path.abspath(os.path.dirname(sys.argv[0])) memorizza in dirp il path assoluto dello script e del file di dati visto che si suppone siano nella stessa directory.

le righe 15-18:

proc = subprocess.Popen(command, shell=True, 
		stdout=subprocess.PIPE, 
		stderr=subprocess.PIPE)
proc.wait()

eseguono una pipe con il il comando command definito precedentemente (riga 12).

il risultato viene salvato nella variabile outp, riga 19 outp = str(proc.stdout.read()). Popen restituisce una tupla di bytes per cui è necessario trasformarla in stringa con str().

A questo punto un ciclo righe 21-28 cerca le substringhe cerco all’interno dei possibili link, quelli con <a href="#. Siccome il link (trovato) può essere più lungo di cerco non uso l’operatore == ma in.

Provo:

b1

Adesso il motivo dello script: nel terminale quelle righe sono attive. Posizionando il cursore del mouse sopra uno e facendo click con il tasto destro ottengo

b2

e con Apri collegamento apro nel browser a quel link interno il manuale.

Non resta che dare un nome sensato allo script, renderlo eseguile e spostarlo in ~/bin, dove dev’esserci anche il documento HTML.

b3

Non mi è venuto in mente niente di meglio di baiuto, da Bash aiuto :grin:
:mrgreen:

Racket e l’arcotangente iperbolica

CNJ

In in precedente post era rimasta in sospeso una domanda: quanto vale l’arcotangente iperbolica di -2? A differenza di Common Lisp (CL) Racket liscio risponde male; o almeno diversamente da CL, Wolfram Alpha e altri. Come mai?

Uhmmm, sembra una cosa complessa. Intanto conviene partire da Wikipedia (come faremmo senza la Wiki? (auto-cit.)) che ci da la formula:

wkatnh

Sembra semplice. Però c’è scritto che vale solo per il dominio ]-1, 1[ :sad: E sì, logico: per x = 1 il denominatore della frazione si annulla :sad: E per x < -1 la frazione ha valore negativo e il logaritmo… :sad:

Insomma non tanto semplice, anzi complessa :wink:

Ma, when the going gets tough, (cit.) Smettila, ti sbianchetto! sei ripetitivo!!!

C’è il Web, googlando spesso si trova, ecco:

, era una cosa complessa, cioè semplice ma bisognava usare i numeri complessi :grin:
Nota per qualcuno: sì lo so che dal post precedente era chiarissimo ma se non facevo un po’ di manfrina questo post sarebbe stato troppo breve e poi i grafici della funzione nel piano complesso mi sembrano molto interessanti, io da solo non ci sarei riuscito.
Nota perso incubosa: meno male che ho già passato gli esami di mate & dintorni, pensa se a un prof di cattivo umore viene in mente di chiederti qual è il dominio di arctanh(z). Prof, dai, lo so che (forse) sono paranoie ma … :roll:

OK, tutto ciò premesso Racket va alla grande:

h0

proprio come dicono gli altri nel post citato precedentemente.

Perso (sì, lo so, si dovrebbe dire personalmente, me l’hanno fatto notare e sono anche stato sgridato, ma è un adattamento dal français, prendetevela con il mio ‘mico J-C o immaginate che ci sia l’accento sulla O) trovo lo script elegantissimo, tanto da riprodurlo qui di seguito:

#lang racket

(define (atanh x)
  (if (= x 1)
    "+/- infinity"  
    (* 1/2 (log (/ (+ 1 x) (- 1 x))))))

La funzione si riduce a una sola riga, inserita in un test if per discriminare la condizione di infinito (non ho indagato per il segno, who cares?). Notare che i numeri per Racket (OK, per il Lisp) non sono quelli dei successori di Algol (e Fortran).

Si può fare con Python? Io sono noto come evangelista Python che per tante cose è ottimo e meriterebbe di più e allora devo dire sì, certo.

C’è solo da tener conto di una cosa: i numeri complessi, non ci sono di default, serve il modulo cmath, presente fin dall’installazione del linguaggio. Io uso (e raccomando) la versione 3.x ma è uguale a quello della versione precedente (che consiglio solo in caso di codice esistente o dipendente da moduli non disponibili per la 3, per esempio Wx).

Ecco:

#!/usr/bin/python3

import cmath

def atanh(x):
    if (x == 1):
        return "+/- infinity"
    else:
        return 0.5 * cmath.log ((1 + x) / (1 - x))
        
#test
x = 0
print(x, atanh(x))
x = 1
print(x, atanh(x))
x = 2
print(x, atanh(x))
x = -2
print(x, atanh(x))

h1

OK, ah! con riferimento al post precedente sull’argomento: Racket promosso summa cum laude, nèh. Ma –si sa– Racket rockz :grin: :wink: :roll: :mrgreen:

Un quiz, soluzioni con Python e Racket

bach-origTrovare quel numero che diviso per 2 ha come resto 1, diviso per 3 ha sempre resto 1, e ugualmente diviso per 4, per 5 o per 6 ha sempre resto 1, ma se viene divso per sette dà resto zero.
Federico Peiretti, Il matematico si diverte, Longanesi 2010, p.83. riferito a Claude-Gaspard Bachet.

Diophantus-cover

Claude-Gaspard Bachet è un matemeatico (e non solo) importante, che giustifica l’uso del quiz molto semplice ma devo fare pratica; e poi c’era anche il mio amico GG (prossimamente, forse…).

Ancora una cosa: l’immagine iniziale è presa da Gallica, qui.

Sono anche in regola con le condizioni d’uso. E grazie Gallica e Bibliothèque nationale de France :grin:

Ah! il problema lo trovate a p.199 del libro originale corrispondente a p.218 del PDF.

OK, siccome sono niubbo provo prima con Python.
Occorre trovare quel numero divisibile per 7 che ha modulo 1 per il minimo comune multiplo di {2, 3, 4, 5, 6}. La funzione per il calcolo del minimo comune multiplo (lcm) l’ho copiata da Rosetta Code.

Quindi ecco, Python, cgb.py:

#/usr/bin/python3

def lcm(*values):
	values = set([abs(int(v)) for v in values])
	if values and 0 not in values:
		n = n0 = max(values)
		values.remove(n)
		while any( n % m for m in values ):
			n += n0
		return n
	return 0

#main
mcm = lcm(2, 3, 4, 5, 6)
found = False
n = 0
while not found:
	n += 1
	found = ((mcm * n + 1) % 7) == 0
print(mcm * n + 1)

py

E con Racket? bèh, qui sono ancora un po’ (tanto) niubbo ma insomma…

E poi c’è la reference in locale, comodissima:

doc

Sì, bash si lamenta di Firefox ma solo per far vedere che c’è anche lui…

Ma Racket? OK, ecco cgb.rkt:

#lang racket

(define mcm (lcm 2 3 4 5 6))
(define num
  (let cgb ([n 1])
    (if (positive? (modulo (add1 (* n mcm)) 7))
      (cgb (add1 n))
      (add1 (* n mcm)))))
(print num)
(newline)   

rkt
La funzione per il calcolo del minimo comune multiplo (lcm) è predefinita :grin:
Il codice è elementare, da niubbo, costruito traducendo quello di Python. Ho usato troppe variabili; ho ripetuto un calcolo numerico una volta più del necessario. Prometto solennemente che in futuro sarò più funzionale.
Giustificazioni: 1) sono niubbo; 2) stavo propagandando Racket a una possibile vittima; con 3) paura di fare una figuraccia.
Poi a demo fatta ho dimenticato il tutto per una settimana, quasi. Ma devo fare pratica, per questo lo pubblico anche se non ottimale :mrgreen:

Nota: corretto un erroraccio, avevo scritto “divisore” al posto di “multiplo”. Grazie a Roberto Giacomelli :grin:

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.

Segui assieme ad altri 89 follower