Banshee's stuff

An aleph-zero potpourri blog...

Alias Method

| Comments

Need to generate random samples from a given discrete distribution? The Alias Method (wonderfully described here) comes to mind… for those who haven’t heard of it it’s a simple but powerfull $\Theta(1)$ random generator with a $\Theta(n)$ initial setup time, so… need to generate random samples from a given discrete distribution in Scala? Check out this implementation.

PS: I love github’s gist feature!

Life

| Comments

Or the game of life written in Scala with a little bit of Swing for the gui.

Let’s explore this code a little bit…

The basic idea is to visualize a Set[Coord] instances on the graphical grid and obtain, with every iteration, the new Set of alive cells.

In order to do that let’s define our beginning state inside the Life main object and create an iterable element using Iterator.iterate method..

1
2
3
4
5
6
object Life extends SimpleSwingApplication {
  val startData: Set[Coord] = Set(/* initial state */)
  val it = Iterator.iterate(Generation(startData))(_.nextGeneration)
  // setup swing window components and 
  // a runnable element to use as an "updater"
}

The Generation class is a extended Set[Coord] which is able to obtain the nextGeneration concatenating (still) alive cells with newborn cells

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Generation(val alive: Set[Coord]) extends Set[Coord] {
  // Set contract methods...

  // get all neighbors for every cell, group by cell
  // and get a tuple with Coord and neighbors count
  private val neighbors = alive.toList flatMap(_.neighbors) groupBy (identity) map { case (c, l) => (c, l.size) }
  // define a generic method to obtain a filtered selection of cells
  private def neighborhood(filter: Filter) = for (filter(coord) <- neighbors) yield coord
  // obtain new born cells 
  // (ie the ones that meet newborn filter requirements)
  private def babies = neighborhood(newborn)
  // obtain current alive cells, watch out for the "alive &" stuff...
  private def adults = alive & neighborhood(stable).toSet
  // concatenate adults with babies
  def nextGeneration = Generation(adults ++ babies)
}

Filters are defined in Generation Object as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
object Generation {
  // case class already defines an apply() method so
  // let's only define an unapply method which
  // accepts a function((Coord, Int)) to Option[Coord]
  // as filtering logic
  case class Filter(f: ((Coord, Int)) => Option[Coord]) {
    def unapply(t: (Coord, Int)): Option[Coord] = f(t)
  }
  def apply(alive: Set[Coord]) = new Generation(alive)

  // if a cell has 3 neighbors it's ok for a new birth
  val newborn = Filter {
    case (c, 3) => Some(c)
    case _ => None
  }
  // 2 or 3 neighbors are ok...
  val stable = Filter {
    case (c, 2) => Some(c)
    case (c, 3) => Some(c)
    case _ => None
  }
}

The last interesting stuff is the implicit conversion from Tuple to Coord objects

1
  implicit def tupleToCoord(t: (Int, Int)): Coord = apply(t._1, t._2)

Now add some graphic code and here we are:

Update (04 feb): code is now stored on github

Pulizie di Primavera

| Comments

Questa volta non ci casco, è inutile promettere di seguire questo blog quando so benissimo che ci sono talmente tante cose da fare in una vita che già spazzare il pavimento di casa e portar fuori l’immondizia fanno passare in secondo-terzo-quarto piano le routinarie operazioni di igiene dovute al proprio sito personale.

D’altra parte, visto lo stato pietoso in cui versava il mio dominio, era necessario fare qualcosa… tanto per dare un segno di vita!

Innanzi tutto si imponeva un cambio di look, font decisamente troppo piccolo e magro per una lettura piacevole e riposante, tema eccessivamente bianco e troppo spazio vuoto. Non potevo, tuttavia, limitarmi alla ricerca/creazione/modifica di una skin qualsiasi per wordpress, troppa roba da scartabellare (1465 temi al momento!) e un certo malessere al pensiero di imbastire nuovamente la baracca:

  • wordpress (che ormai avevo riempito di plugin in preda al delirio della sperimentazioni);
  • database (mysql) con annesso phpmyadmin;
  • setup del pannello di amministrazione (plugin…);
  • cercare un plugin come-dico-io™ per la visualizzazione delle gallery;
  • aggiornamenti automatici;
  • uso di un editor html per scrivere i post;
  • etc etc…

Insomma, dopo svariati anni di utilizzo, e pur considerandolo uno strumento eccezionale ed estremamente flessibile, wordpress mi ha rotto. La ricerca di alternative (e nemmeno io sapevo esattamente di quale genere queste potessero essere) mi ha portato a scoprire l’esistenza di Jekill prima e di Octopress dopo… e qui ci sta una spiegazione per chi non è avvezzo a questi blogging framework per hacker (come si autodefiniscono).

Mai Portare i Filosofi a Cena

| Comments

Ovvero il problema dei filosofi a cena risolto utilizzando Scala ed Akka 2.0 (l’attuale snapshot)

(dining_philosophers.scala) download
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.Props
import akka.util.duration._
import scala.actors.threadpool.TimeUnit
import akka.actor.ActorSystem

sealed trait TableMessage
case class Take(philosopher: ActorRef) extends TableMessage
case class Taken(fork: ActorRef) extends TableMessage
object Eat extends TableMessage
object Think extends TableMessage
object Busy extends TableMessage
object Put extends TableMessage

class Fork extends Actor {
  import context.become

  def available: Receive = {
    case Take(philosopher) =>
      become(taken)
      philosopher ! Taken(self)
  }

  def taken: Receive = {
    case Take(otherOne) =>
      otherOne ! Busy
    case Put =>
      become(available)
    case x => println(x)
  }

  def receive = available
}

class Philosopher(left: ActorRef, right: ActorRef) extends Actor {
  import context.become
  import context.system

  def hungry: Receive = {
    case Taken(this.left) =>
      become(waiting_for(right, left))
    case Taken(this.right) =>
      become(waiting_for(left, right))
    case Busy =>
      become(denied)
  }

  def eating: Receive = {
    case Think =>
      println(self.path.name + " puts down his forks and starts to think")
      become(thinking)
      left ! Put
      right ! Put
      system.scheduler.scheduleOnce(3 seconds, self, Eat)
  }

  def waiting_for(toWaitFor: ActorRef, taken: ActorRef): Receive = {
    case Taken(toWaitFor) =>
      become(eating)
      println(self.path.name + " has taken " + taken.path.name + " and " + toWaitFor.path.name)
      system.scheduler.scheduleOnce(3 seconds, self, Think)
    case Busy =>
      become(thinking)
      taken ! Put
      self ! Eat
  }

  def thinking: Receive = {
    case Eat =>
      become(hungry)
      left ! Take(self)
      right ! Take(self)
  }

  def denied: Receive = {
    case Taken(fork) =>
      become(thinking)
      fork ! Put
      self ! Eat
    case Busy =>
      become(thinking)
      self ! Eat
  }

  def receive = {
    case Think =>
      become(thinking)
      system.scheduler.scheduleOnce(1 seconds, self, Eat)
  }
}

object Dining extends App {
  val system = ActorSystem("DiningTable")
  val forks = for (i <- 1 to 5) yield system.actorOf(Props[Fork], "fork" + i)
  val philosophers = for {
    (name, i) <- (List("Pluto", "Socrates", "Aristotle", "Pythagoras", "Zeno").zipWithIndex)
  } yield system.actorOf(Props(new Philosopher(forks(i), forks((i + 1) % 5))), name)
  philosophers.foreach(_ ! Think)
}

ispirato da questa soluzione, ossia da questa

Eppure…

| Comments

Non si può negare che il male esista; occorre vederlo e prendere delle precauzioni. Ma anche se esiste, non è una buona ragione per non vedere altro.

Purtroppo, ci sono persone che si compiacciono nel male come se fosse per loro un nutrimento: vanno matti per gli scandali, le catastrofi, le sordidezze…
Sostengono di parlare del male per denunciarlo, per combatterlo.
No, è falso; ne parlano perché lo amano, e ne godono. Senza il male si annoierebbero, non avrebbero niente da dire, niente da scrivere. Bisognerebbe abituare i bambini sin da piccoli a interessarsi di preferenza a tutto ciò che è bello, buono, nobile, puro. È talmente più benefico per la loro formazione! Del resto, è questa la vera pedagogia: sforzarsi di nutrire nei bambini l’amore per tutto ciò che esiste di meglio, perché solo l’amore per la bellezza, per la bontà e per la giustizia permette veramente di neutralizzare il male in se stessi e negli altri.

Omraam Mikhaël Aïvanhov

Mi fa venire in mente certa parte dell’Italia… ma non solo per (s)fortuna

Essere Sviluppatori Oggi

| Comments

Dunque, spiegatemi se ho capito bene, io mi giro un attimo e succede che Oracle (proprio quella sudiciona dell’omonimo database) si compra Sun (e quindi MySql) mandando a puttane OpenOffice e Java (con tanto di stupida causa contro Google) e nessuno dice un tubo, se MS avesse provato a comprare un vendor linux sarebbero stati pronti a farsi saltare in aria 1000 pinguini imbottiti di tritolo, qui il silenzio e la fuga dei dipendenti…

Non paghi di tutto questo casino Apple decide che è ora che Java e Flash si arrangino e che l’utente non deve averli nel suo pc splendidamente integrati come sempre era stato; così può propinare l’app store anche sulle macchine di classe desktop/notebook, a questo punto togliamo la possibilità di installare applicazioni da dvd, che ne dite? Il futuro è un’unica famiglia di iPad con/senza telefono, con/senza tastiera fisica e col monitor più o meno grande? Wow…

In tutto questo MS decide che effettivamente Vista era una crosta senza fine e lancia 7, e, visto che il mondo si sta spostando verso i sistemi operativi mobile (che dei pc non gliene fotte più a nessuno per muovere i soldi veri), capisce di dover cestinare quella schifezza di Windows Mobile e scriverne uno che sia vagamente utilizzabile ed in linea con gli standard attuali e ora, con solo un paio d’anni di ritardo, si getta anche lei nella mischia. I miei personali auguri ma mi sa che non ci sono idee chiare li dentro (del resto Ballmer non ha ancora capito qual è il lavoro per cui viene pagato…)

Abbiamo parlato di mobile? E il supergigante Nokia? Che ha fatto di bello? Comprato Symbian, lo ha rilasciato open, lo ha fatto morire, ne ha ripreso lo sviluppo, l’ha rinnegato e poi ha deciso che il futuro è MeeGo. Bravi, se continuate così persino l’LG vi mangerà il culo nella fascia degli smartphone, arrendetevi e ricacciate in gola l’orgoglio ve ne prego che l’hw lo fate bene :( (persino Sony si è arresa e sembra sulla scia di una certa ripresa…)

Nel mentre Google continua a muoversi in modo apparentemente casuale, comprando aziende di cui non sa cosa farsene (salvo poi riuscire a farle fruttare lo stesso :) ), producendo un sistema operativo da utilizzare su device connesse alla rete, e interpretando correttamente (almeno secondo me) la prossima lotta nel panorama aziendale informatico: connettere qualsiasi cosa alla rete e usarla per vendere/distribuire/promuovere qualcosa (tipicamente merda ma ci son tante cose anche carine, credo).

Apple lo sta facendo da più tempo, Google lo sta facendo su più fronti, MS sta cercando di capirlo, chissà cosa ne tireranno fuori.

E se vi state chiedendo cosa centri la parte iniziale su Sun è presto detto, il backend di tutto questo marasma di roba (a parte per MS, forse) in che linguaggio credete che sia stato e sarà scritto? Maremma che casino, per fortuna me ne son tirato fuori… è dura essere sviluppatori oggi…

P.S. se il discorso vi pare sconfusionato è perché è stato scritto di getto, sono certo che chi deve capire, tuttavia, capirà

Comunicazione di Servizio

| Comments

Siamo di nuovo in piedi, risolti dei “piccoli” problemi di funzionamento del tutto.

Shit happens, capita anche nelle migliori famiglie :)

Suunto Vector Hr, Molto Più di un Orologio?

| Comments

Dovete sapere che per me l’acquisto di un oggetto personale si riconduce a due sole possibili modalità d’azione: nella prima compro la prima cosa che vagamente assomiglia a quello che mi serve e viviamo tutti felici e contenti; nella seconda modalità (tipicamente mi sto occupando di un oggetto in qualche modo “tecnico” e, quindi, in grado di stimolare i miei istinti geek, tra gli altri) la valutazione è lunga, difficile e la decisione, in mancanza di una chiara supremazia a livello di caratteristiche o rapporto qualità/prezzo, è travagliata.

Ovviamente questo è stato il caso per l’acquisto di questo orologio da polso con millemila funzionalità annesse.

In prima battuta stavo cercando un orologio dotato di funzionalità evolute come cronometro/timer, unica vera mancanza del mio precedente (e ancora in servizio) G-Shock, e/o un orologio dotato di funzionalità ABC, ovvero altimetro, barometro, bussola (compass in inglese), possibilmente con alimentazione solare e una buona resistenza costruttiva. Risparmiatevi pure la fatica… non ne esistono con tutte queste funzioni incluse (o se esistono e non li conosco lasciate pure un commento perché ne sarei davvero felice :) ).

Insomma, per fare breve una storia lunga, la scelta si è ridotta a due modelli, il Casio Protrek PRW-2000 o il Suunto Vector, disponibile anche col l’opzione del cardiofrequenzimetro (HR). Da bravo metodico ho individuato i miei personali Pro/Contro dei due modelli e poi ho proceduto alla scelta…

Pro del Casio:

  • alimentazione solare;
  • retroilluminazione automatica (con un sensore di inclinazione) attivabile (voi riderete ma in ambulanza ogni tanto torna utile);
  • 5 allarmi giornalieri;
  • vetro minerale e, in generale, costruzione meno robusta dei G-Shock ma comunque robusta.

Contro del Casio:

  • sensoristica “sacrificata” al risparmio energetico, tipicamente con letture automatiche meno frequenti dei sensori con annesso logbook “striminzito” e che culminano, infine, con l’impossibilità di retroilluminare il display durante l’uso della bussola e, in generale, sensori meno precisi (almeno così dicono sui vari forum, le prove in negozio valgono quel che valgono…).

Pro del Suunto:

  • sensoristica senza compromessi di uso e di precisione con funzionalità complete di logbook automatico oggettivamente più utilizzabili e chicche come la velocità di salita/discesa “istantanea”;
  • bolla per poter allineare la bussola (oh, se mi dai una cosa tanto vale darmela bene…);
  • intervallometro per allenamenti e, in genere, funzionalità migliori per timer/cronometro rispetto al Protrek;
  • cardiofrequenzimetro (opinabile lo so);
  • per quanto non solare le batterie sono cmq sostituibili dall’utente tranquillamente;
  • lettura dell’altimetro con compenso della temperatura (i Casio sembrano avere molteplici problemi in tal senso).

Contro del Suunto:

  • costruzione così così, intendiamoci non è che non sembri robusto o non sia costruito bene, è solo che i Casio danno delle sensazioni decisamente migliori da questo punto di vista…
  • vetro di plastica… ragazzi in un orologio di questa fascia di prezzo sinceramente mi fa un po’ tristezza;
  • 3 sole sveglie giornaliere (voi riderete ma io le uso… è il motivo per cui ho scartato il Suunto Core dalla lista dei papabili). Alla fine la scelta è caduta sul Vector HR un po’ per l’estetica (il modello bianco che ho comprato mi piace assai), un po’ per il cardio e un po’ per i compromessi a cui l’alimentazione solare fa scendere nel Protrek. Se deve essere orologio ABC che almeno lo faccia bene e gli cambierò le batterie ogni tanto, al massimo il prossimo orologio della mia collezione sarà un G-Shock solare :P

Ed eccoci giunti all’oggetto vero e proprio, una sola premessa ulteriore: personalmente trovo l’usabilità degli orologi Casio superiore a tutti gli altri, mi sembrano semplicemente più “logici”, come accade per le reflex Nikon rispetto alla concorrenza questo accade per gli orologi, da questo punto di vista il Suunto è stato da parte mia un “azzardo” e una “sfida” ai loro prodotti (ok, ai finnici non gliene sbatterà niente se a me piace o no l’usabilità del loro orologio ormai che l’ho comprato…).

Diciamo le cose buone per prime, l’orologio si comporta bene, è comodo, molto leggibile pur essendo completamente digitale ed esteticamente mi sta bene indosso (il quadrante è piuttosto grande…), una volta completato il setup iniziale (data/ora/unità di misura) la visualizzazione delle informazioni base è intuitiva e, rispetto al Casio, ammetto che è finalmente un piacere vedere riportata la data con prima il giorno e poi il mese (anche se ormai mi ci ero talmente abituato che non ci facevo più caso). Le funzioni base sono generalmente accessibili con pochi click e l’intuitività è abbastanza buona una volta capito il meccanismo modalità/sottomodalità in cui è impostata l’interfaccia utente. In sintesi l’orologio funziona in 5 modalità principali: tempo; altimetro; barometro; bussola e cardiofrequenzimetro; ognuna di queste modalità (ciclabili col tasto in alto a dx) include alcune sottomodalità specifiche per la modalità selezionata in quel momento (ciclabili col tasto in alto a sx). In questo modo è possibile passare, per esempio, dalla visualizzazione del battito cardiaco corrente (modalità cardio) al timer per gli intervalli o al cronometro (due diverse sottomodalità del modo cardio) e via dicendo (guardatevi i manuali online se li volete tutti elencati, non intendo ripetervi tutto qui :) ). I restanti due tasti (dx e sx in basso) svolgono generalmente funzione di +/- per i valori da editare o start/stop e reset per le funzionalità di timer/cronometro. A livello di comandi si sente la mancanza di un tasto dedicato per l’accensione della retroilluminazione, tenere premuto per due secondi il tasto di cambio modalità è una discreta rottura per quanto mi riguarda e, in più, il feedback dei tasti non è sempre perfetto e capita di cambiare visualizzazione invece che accendere il display (molto male Suunto…). I logbook del cardiofrequenzimetro riporta FC max/min/media dell’allenamento, data e ora di inizio e durata dello stesso, tempo passato sopra/sotto/internamente alle soglie impostate e durata effettiva dell’allenamento nel caso di ripetute con intervallo di riposo, l’unica pecca è la presenza di un solo banco di memoria per questi dati e quindi è meglio che ve li segnate a parte prima di riavviare il cronometro o il timer per mettere a cuocere la pasta ;) Il logbook dell’altimetro, invece, è dotato di 99 memorie con data/ora della registrazione, durata della stessa, ascesa e discesa totali (con media di velocità di salita/discesa) e numero complessivo di giri (per loro un giro corrisponde ad una salita e discesa verticale di 50 metri o più, non chiedetemi il perché). Pecca di questa modalità è che per iniziare la registrazione bisogna premere DUE volte il tasto + dell’orologio (quello usato per avviare il cronometro o il timer per capirci) senza che le icone visualizzate diano il minimo indizio all’utilizzatore del fatto che sia richiesto un simile comportamento da parte nostra… Ulteriori due difettucci riscontrati sono la sveglia un po’ poco rumorosa (anche se fatta l’abitudine mi riesce comunque a svegliare) e il manuale, il cui filo logico nel trattare gli argomenti sinceramente mi sfugge, sembra davvero che abbiano preso il manuale del modello precedente, senza cardiofrequenzimetro, e ci abbiano infilato dentro le pagine aggiuntive per questa nuova funzione…

Al di la di questi tre problemi (che comunque non ne rovinano la fruizione una volta noti, sveglia a parte se siete un po’ duri d’orecchie) l’orologio è consistente e facile da utilizzare, i sensori si sono rivelati perfetti nell’uso in montagna e la fascia cardio è molto comoda e non si sposta durante l’esercizio, non posso fare paragoni non avendo avuto altri cardio prima ma mi sembra comunque di ottima fattura. In pratica se il vostro hobby è l’escursionismo montano, l’attività fisica e, in particolar modo la corsa, soprattutto la corsa in montagna ma non avete voglia di comprarvi un gps specifico per l’allenamento (come il Garmin Forerunner, tanto per dirne uno) questo è sicuramente il prodotto che fa per voi; se la vostra idea di escursionismo include 6 mesi nell’artico da soli senza rifornimenti probabilmente il pannello solare del Protrek fa al caso vostro  :)