lunedì 19 novembre 2012

Mission Python. Funzioni. Parte quinta

Funzioni, stringhe e un esercizio.
Incominciamo con alcune funzioni di quelle built-in (immediatamente disponibili con il programma).
Naturalmente ci ricordiamo che possiamo trovarle e sapere tutto su di esse all'URL http://docs.python.org/genindex.html , vero?
Il nostro scopo di oggi è di costruire uno script per verificare l'operazione di Kaprekar.
Per chi, come me, non sapesse di cosa stiamo parlando e fosse curioso potrebbe fare un salto qui: Il 6174 e il 495 di Kaprekar

Adesso, sperando che Marco Fulvio non si arrabbi, copiamo & incolliamo l'algoritmo direttamente dal suo post:
  • Prendiamo un qualsiasi numero di quattro cifre, usandone almeno due diverse. (Si possono inserire degli zero anche all'inizio.)
  • Sistemiamo le cifre in ordine decrescente e poi in ordine crescente così da ottenere due numeri di quattro cifre, aggiungendo degli zero iniziali se necessario. 
  • Sottraiamo il numero più piccolo da quello più grande. 
  • Ripetiamo il processo partendo dal punto 2.
Questo processo, conosciuto come operazione di Kaprekar, andrà sempre incontro al suo punto fisso, o kernel, il 6174.

Si può fare? hmmm, sì, forse...
Dai è facile! Python ci fornisce tutte le funzioni che ci servono.
Abbiamo già visto str() e int():
list() trasforma una stringa in una lista i cui componenti sono le singole lettere:
sort() ci ordina la lista:
In realtà sort() è un metodo, ne riparleremo, per adesso vediamola come una funzione. Notare che opera sulla stringa stessa, distruggendo l'originale.

reverse() inverte la lista:
join() unisce i compoenti di una lista in una stringa:
OK, abbiamo tutto quello che ci serve, proviamo (k.py)?

#!/usr/bin/python
# -*- coding: utf-8 -*-

# verifica dell'operazione
# di Kaprekar

import sys

kernel = 6174 # vogliamo arrivare qui

def kcalc(num):
    # se il numero di cifre è minore di 3
    # aggiungo zeri alla fine
    while num < 1000:
        num *= 10

    st = str(num)
    lst = list(st)
    lst.sort()
    t = ''.join(lst)
    piccolo = int(t)

    lst.reverse()
    t = ''.join(lst)
    grande = int(t)

    diff = grande - piccolo
    print num, '->', grande, '-', piccolo, '=', diff
    return diff

# main
N = int(sys.argv[1])
while N != kernel:
    N = kcalc(N)

Troppo facile vero?
Però, aspetta un attimino: si era detto che non funziona per cifre tutte uguali, ecco:
Sembra morto...
L'ho dovuto interrompere con crtl-C.

Beh, il bug si elimina facilmente, basta un controllo.
Anzi, adesso che ci penso: lasciato come esercizio, il primo che indovina un premio meraviglioso.

Juhan

Vi ricordo che l'indice di "Mission Python" lo trovate qui

2 commenti:

  1. Mi da un errore alla linea 23, quella con N = main...
    Dice: list out of range.

    RispondiElimina
    Risposte
    1. Lo so che sono molto in ritardo ma non riesco a riprodurre il tuo errore. Se vuoi mandami una mail con lo script e lo screenshot a n1n0.aegis@gmail.com

      Elimina