13/12/09

Exercice de 'pataprogrammation: le tri à gobelets

Tiens et si on parlait d'informatique, pour changer un peu, et pour rappeler aux moins attentifs de l'assistance que votre serviteur est avant toute chose ce qu'il convient d'appeller un "computer geek"? Mais bon, ne parlons pas d'informatique trop sérieuse quand même, ça s'écarterait du sujet ;-)

Un mien ami, qui fut mien camarade de cours quand nous usions les bancs de la fac d'info de Namur, est il me semble l'instigateur de la 'pataprogrammation, qui est à la programmation ce que la 'pataphysique est à la physique. Je pense que l'amie Wikipedia saura mieux que moi vous expliquer ce qu'est cette fameuse 'pataphysique, retenez surtout que son inventeur est le père de Ubu, ça donne le ton.

Ce joyeux farfelu a donc déliré un jour et inventé le "tri à gobelets" qui est sans aucun doute le moins efficace des algorithmes de tri. L'idée est simple: permutons deux éléments du tableau à trier, choisis au hasard, et répétons l'opération jusqu'à ce que le tableau soit effectivement trié.

Bon, intuitivement c'est une atrocité cet algorithme, mais en fait c'est une atrocité à quel point? Comme le dit son auteur, il s'exécute de façon pas trop péniblement lente pour des tableaux de petite taille, mais avec peu de chance on peut y perdre beaucoup de temps. De plus, l'alogorithme n'a aucune garantie de terminaison autre que la fin des temps. Brillant! Donc pour avoir une mesure, j'ai pondu le programme suivant:


#! /usr/bin/python
# Implementation de l'algorithme de tri par gobelets, invente par Benoit Vleminckx
# http://www.javafr.com/codes/TRI-GOBELET-BEAKER-SORT_48639.aspx

import random

def is_sorted(tab):
""" renvoie True ssi tab est trie par ordre croisant """
for i in range (0,len(tab)-1):
if tab[i] > tab[i+1]:
return False
return True

def beakersort(tab):
"""Trie le tableau tab par l'algorithme du tri a gobelets"""
# pour la science
iterations = 0
while not is_sorted(tab):
iterations += 1
# determination de deux indices aleatoires differents
index1 = -1
index2 = -1
while (index1 == index2):
index1 = random.randint(0,len(tab)-1)
index2 = random.randint(0,len(tab)-1)
# permutation des elements a ces indices
tab[index1],tab[index2] = tab[index2],tab[index1]
print len(tab), iterations
return tab

# Mesures hautement scientifiques!
for tablength in range (3,11):
for testnum in range (0,100):
testtab = range(0,tablength)
random.shuffle(testtab)
beakersort(testtab)


Remarquons que j'y suis optimiste puisque je suppose que chaque application de l'algorithme va effectivement se terminer un jour. Il faut savoir vivre dangereusement parfois...

Conclusion? Pas brillantes du tout. En résumé pour des tailles de tableau allant de 3 à 10 on obtient ceci (valeurs exprimées en nombre de permutations avant achèvement):

LongueurMinimumMaximumMoyenne
30305
4010522
50659117
673779917
781238925096
833019954038792
9113211791937339068
1021080176681424145666


Magnifiquement inefficace, n'est-ce pas?

...la suite par ici...

23/11/09

Première tentative de jardinage miniature, une semaine après

Dimanche dernier j'avais succombé à l'envie subite de reproduire une idée glanée au cours d'une séance de glandage-surfage. C'est une première tentative, je ne sais absolument pas où je vais, d'autant plus que les plantes transplantées ont changé de conditions de lumière, de température, d'humidité...

Finalement je pense ne pas m'en tirer trop mal pour un début. Les brins d'herbe ont un peu poussé, mais aussi un peu jauni. Je soupçonne un léger manque de lumière, l'éclairage a été adapté en fonction. L'éclairage du bureau sur lequel repose ce mini-jardin risque fort de changer dans un plus ou moins court terme, mais de toute façon on reste en intérieur donc si une plante ou l'autre ne sait pas se contenter de la lumière disponible il me restera juste à en trouver une de remplacement.



Jusqu'ici, ça va plutôt bien. Nous verrons bien la suite.

...la suite par ici...

16/11/09

Première tentative de jardinage miniature

Je suis tombé tout à l'heure sur un post assez intéressant du blog Lifehacker à propos de la robustesse de la mousse et de ce fait son adaptation à des mini-jardins d'intérieur. L'idée est que la mousse nécessite pas ou peu de terre, et aucune forme de soin au-delà de l'arrosage. Ça faisait un bout de temps que je voulais mettre de la verdure sur mon bureau, donc allons-y!

Petite expédition pour obtenir de la matière première, laquelle n'a pas été particulièrement pénible; ça aide d'avoir un grand jardin deux étages plus bas. Me voilà donc avec un peu de mousse décrochée du sol, que j'ai retirée en découpant autour d'elle et en glissant une spatule dessous pour la soulever sans l'arracher. La terre supplémentaire était sous la mousse prélevée, ainsi je suis sûr qu'elle est appropriée. Les cailloux sont du gravier qui servait à mettre un couche de drainage dans le fond des pots de fleur. Réutilisons!


Le conteneur quant à lui est un verre d'une certaine variété d'une certaine marque de gueuse, certainement subtilisé lors d'une bacchusienne expédition entre amis, qu'importe. Les audacieux font ce genre de jardin miniature dans le fond d'une bouteille de vin... heu... un autre jour! Je le remplis de terre jusqu'à atteindre presque l'endroit le plus large du ballon, ça me donnera de la marge de manœuvre.


J'y place les plus beaux morceaux, découpés au couteau, les pierres prennent place pour former un arrière-plan sympathique. Il faudra certainement un peu de temps avant que la croissance de la mousse ne remplisse les interstices, mais je sais être patient :)


Le surplus a trouvé sa place dans un autre pot de format différent. Les gourmands attentifs auront reconnu qu'il a contenu dans une autre vie une délicieuse crème brûlée.


Voilà, reste à voir comment le temps fera son office, et si l'expérience s'avère concluante je pourrai semer de la verdure miniature un peu partout.

...la suite par ici...

01/11/09

Un peu de mathématiques d'amateur qui ne se prend pas au sérieux...

Un illustre collègue adepte de l'adjectif "outrant" et moi-même avons décidé que la somme d'un entier et de son carré serait un nombre "outrant", ce qu"on peut presque-formaliser:

n + n^2 , où n est un entier positif


Qu'on peut exprimer comme le produit de deux entier consécutifs:

n(n + 1)

Les premiers nombres outrants sont 0, 2, 6, 12, 20, 30, 42, 56, 72, 90, 110, 132, 156, 182, 210, 240, 272, 306, 342, 380, 420, 462, 506, 552, 600, 650...

On appelle "puissance outrante" le nombre outrant de base n, 5 à la puissance outrante vaut 30. On note la puissance outrante par un exposant O (la lettre, pas le chiffre), comme dans 11^O = 132.

En fait en cherchant un peu, ces braves petiots n'ont aucune propriété amusante, si ce n'est que 42 en fait partie (puisque c'est 6 à la puissance outrante), ce qui est un fait qui a été accueilli avec beaucoup de joie puisque l'outrant compagnon de mathématiques du dimanche est presque aussi fan de l'humour d'H2G2 que moi-même. 42 est un nombre outrant, et ça c'est vraiment outrant!

L'avantage est aussi qu'un nombre outrant n'est pas fonction des précédents, ce qui facilite la tâche quand pour l'une ou l'autre outrante raison on a besoin de nombres outrants quelconques éventuellement très grands. De la même manière, si on veut obtenir le plus petit nombre outrant qui soit supérieur à un nombre donné, il suffit d'élever sa racine à la puissance outrante. Pratique.

Allez, plus sérieusement, le produit de deux entiers consécutifs a été déjà baptisé et ausculté. On appelle ces nombres les "nombres oblongs", "nombres proniques", ou encore "nombre hétéroméciques". Pourquoi oblong? Parce qu'exprimés figurativement ça donne quelque chose comme ceci:


**

***
***

****
****
****

*****
*****
*****
*****


Un certain John Conway en a parlé en long et en large, d'ailleurs. Oui, le même John Conway que le jeu de la vie.

Je sais, ça ne sert à rien, c'est d'ailleurs pour ça que c'est indispensable.

...la suite par ici...

29/08/09

Deux ans de statistiques LastFM

Ah tiens, ça fait deux ans aujourd'hui. Deux ans que je suis inscrit à LastFM et que son brave petit scrobbler collecte avec patience et méthode mes habitudes musicales. Enfin presque, il manquait jusqu'il y a peu tout ce que j'écoute sur mon iPod, puisque le scrobbling d'iPod n'était pas exactement au point.

Bref...

Pour ceux qui ne connaissent pas encore LastFM, le principe est plutôt simple. Les utilisateurs laissent un logiciel/plug-in collecter des données statistiques sur les morceaux de musique qu'ils écoutent et envoient tout ça sur le site pour se constituer un profil de mélomane. Sur base de ce profil et de folksonomie, le système établit des corrélations de style entre différents artistes; au final ça lui permêt de conseiller à l'utilisateur des découvertes musicales qui devraient lui plaire (et croyez-moi c'est la partie impressionnante, ils se trompent rarement) et lui présenter d'autres utilisateurs aux goûts similaires.

Evidemment, plus on écoute, plus les statistiques sont parlantes, et plus les déductions sont fiables. Avant 500 titres écoutés le système n'essaie même pas de proposer quoi que ce soit, d'ailleurs. Par contre quand on dépasse les 10000 titres il devient d'un précision presque effrayante.

Je me suis inscrit à LastFM le 28 août 2007. Depuis cette date j'ai écouté 37058 titres de 1196 artistes différents et s'il fallait résumer mes goûts à quelques étiquettes elles seraient "industrial, electronic, rock, metal et ebm", amusant pour quelqu'un qu'on appelle "le métalleux" quand même ;). Pas si simplement métalleux que ça finalement, l'homme en noir.

D'ailleurs quand on classe les artistes par nombre d'écoutes ça devient encore plus amusant. En partant du plus écouté ça donne:

  1. Amon Tobin - 819 écoutes

  2. Nine Inch Nails - 808 écoutes

  3. Metallica - 736 écoutes

  4. Combichrist - 547 écoutes

  5. The Chemical Brothers - 544 écoutes

  6. Johnny Cash - 529 écoutes

  7. Suzanne Vega - 510 écoutes

  8. Punish Yourself - 483 écoutes

  9. Caliban - 464 écoutes

  10. System of a Down - 432 écoutes

  11. Lofofora - 412 écoutes

  12. Converge - 382 écoutes

  13. Heaven Shall Burn - 378 écoutes

  14. Tori Amos - 365 écoutes

  15. 65daysofstatic - 354 écoutes

  16. Walls of Jericho - 344 écoutes

  17. Slipknot - 316 écoutes

  18. Baroness - 297 écoutes

  19. Alchemik Babylon Beats - 285 écoutes

  20. The Cinematic Orchestra - 284 écoutes

  21. Ultra Vomit - 269 écoutes

  22. Depeche Mode - 267 écoutes

  23. As I Lay Dying - 264 écoutes

  24. The Faint - 257 écoutes

  25. VNV Nation - 255 écoutes

  26. Creedence Clearwater Revival - 245 écoutes

  27. Cat Power - 243 écoutes

  28. The Cure - 242 écoutes

  29. Tom Waits - 230 écoutes

  30. Aerosmith - 224 écoutes

  31. IAMX - 214 écoutes

  32. Autechre - 211 écoutes

  33. Korn - 210 écoutes

  34. Tamtrum - 207 écoutes

  35. The Dillinger Escape Plan - 202 écoutes

  36. Peter Pan Speedrock - 201 écoutes



Soyons arbitraires et disons qu'au-délà ce n'est plus forcément représentatit, mais on y croise entre autres Renan Luce, Kings of Convenience, Motörhead, Spiritual Beggars, Björk, Nick Cave, Portishead, Leonard Cohen, Crass, Oi Polloi, Jeff Buckley, P!nk, Neil Young, Birdy Nam Nam, Popa Chubby, Mark Knopfler, Einstürzende Neubauten, Elle Fitzgerald, Zenzile et Anthrax ... j'ose m'autoriser à dire que j'ai des goûts variés ;)

Allez, je ferai un état des lieux dans un an alors. En attendant les très curieux peuvent aller par ici.

Music!


...la suite par ici...

24/08/09

Réparation d'un jack de guitare

J'avais il y a quelques temps racheté du matériel (ampli, V-Amp, câbles) à un ami généreux qui préférait confier tout ça à mes mains débutantes plutôt que de le laisser prendre la poussière. Remy, si tu me lis, grand merci à toi ;-) Mais bon, dans le tout il y avait un câble jack qui souffrait de quelques petits faux contacts qui étaient assez désagréables (si vous n'avez pas encore entendu le son d'un contact qui se refait, amplifié... ça vaut le détour). Donc une intervention était de mise.



C'est le genre d'intervention qui peut faire peur quand on ne sait pas par où chercher, et qui est souvent facturé scandaleusement cher en magasin de musique. En fait le cas extrêmement fréquent c'est qu'à forcé de manipuler le câble sans délicatesse le fil s'arrache du jack. Vérification faite, d'un côté tout va pour le mieux dans le meilleur des mondes:


... mais de l'autre les soupçons sont confirmés (et le petit isolant supplémentaire me laisse supposer qu'il n'en est pas à sa première réparation):


Allons-y alors, d'abord dénuder un peu du câble, pour pouvoir dénuder un peu du fil allant à la pointe et ainsi en avoir assez à nu pour le ressouder:


Ce faisant je remarque que l'isolant a cassé, un point de colle salvateur remettra le morceau tombé (qu'on voit à l'arrière-plan près de la pince):


Paré à retirer l'ancienne soudure (oui madame, à la pompe, oui je suis un bourrin):


C'est-y-pas propre ça madame?


Le fil entré dans son petit trou, prêt à être ressoudé:


... et soudé:


On referme le tout, oui il y a un sens bande de brutes:


Et voilà, ready to rock!


L'opération aura duré quelque chose comme un quart d'heure sans se presser. Et avec ça j'ai cinq mètres de liberté au lieu de deux. Ça valait la peine donc ;-)

...la suite par ici...

03/07/09

Project Euler: solution au problème 24, en Python

On commence les deux mois d'été par le suivant des problèmes eulériens, à savoir le Problème 24. Sachant ce qu'est une permutation, on précise qu'on veut obtenir les permutations d'une suite de nombres dans l'ordre lexicographique (ce qui revient à la relation d'ordre du plus petit au plus grand), et on demande quelle est la 1000000ème permutation de la liste 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

L'algorithme est plutôt évident, et j'utilise ici le copain yield qui me permet d'avoir un générateur itérable plutôt de devoir générer toutes les permutations avant d'en prendre la millionnième.


#! /usr/bin/python

# 2009/07/03 - euler024.py
# Solution au Probleme 24 de Project Euler
# http://projecteuler.net/index.php?section=problems&id=24
# Jean Karim Bockstael - jkb@jkbockstael.be


def permutations_gen(string):
if (len(string) == 1):
yield string
else:
for i in range(len(string)):
for subperm in permutations_gen(string[:i] + string[i+1:]):
yield string[i] + subperm

def euler24(string, num):
cnt = 0
for perm in permutations_gen(string):
cnt += 1
if cnt == num:
return perm

print euler24("0123456789", 1000000)



...la suite par ici...

26/06/09

Project Euler: solution au problème 28, en Python

Ça faisait longtemps que je n'avais pas gratifié mon blog d'un des si particulièrement passionnants problèmes de Project Euler. Il était grand temps d'y remédier, donc voici une solution au problème 28.

L'idée est de remplir une grille carrée de nombres, de dimension impaire, qui est remplie des entiers successifs en spirale partant du centre et allant vers la droite et le bas. Aga? En gros, ayant ce genre de chose:


21 22 23 24 25
20 7 8 9 10
19 6 1 2 11
18 5 4 3 12
17 16 15 14 13


La somme des éléments de deux diagonales de ce carré de dimension 5 vaut 101. Que vaut la somme pour un carré de dimension 1001?

Je vous avais présenté mon pote Récursion?

#! / usr/bin/python

# 2009/06/26 - euler028.py
# Solution au Probleme 28 de Project Euler
# http://projecteuler.net/index.php?section=problems&id=28
# Jean Karim Bockstael - jkb@jkbockstael.be

def sum_of_diagonals(dimension):
if (dimension == 1):
return 1
else:
corner_tr = dimension ** 2
corner_tl = corner_tr - dimension + 1
corner_bl = corner_tl - dimension + 1
corner_br = corner_bl - dimension + 1
corner_sum = corner_tr + corner_tl + corner_bl + corner_br
return corner_sum + sum_of_diagonals(dimension - 2)

print sum_of_diagonals(1001)


...la suite par ici...

24/06/09

Codechef: Petit déjeuner de l'autre côté du miroir

The Codechef, le concours de programmation organisé par Directi, propose depuis peu deux problèmes par jour via Twitter. Ce matin, le problème est de compter le nombre d'entiers inférieurs à 1000 qui, quand on les ajoute à leur image miroir, forment un entier qui n'est composé que de chiffres impairs.

Exemple simple:

...
20 + 02 = 22 NON
21 + 12 = 33 OUI
22 + 22 = 44 NON
...


Et comme d'habitude, j'ai sorti l'ami Python, celui qui nous veut du bien.


#! /usr/bin/python
# Codechef Twitter Daily 2009/06/24
# How many numbers below 1000 which when added with their respective mirror images result in a number with entirely odd digits?
# 2009/06/24 - Jean Karim Bockstael - jkb@jkbockstael.be


def reverse_number(num):
return int(str(num)[::-1])

def is_all_odds(num):
for digit in str(num):
if (int(digit) % 2 == 0):
return False
return True

def count_mirrors(max):
n_mirrors = 0
for num in range(1, max):
if is_all_odds(num + reverse_number(num)):
n_mirrors += 1
return n_mirrors

print count_mirrors(1000)



...la suite par ici...

16/06/09

Tiens j'avais oublié ça...

Il est un fait établi qu'il m'arrive souvent de perdre de vue quelque chose tant mes occupations et projets sont nombreux et variés. Il est également un fait établi qu'il m'arrive dans ma distraction d'effectuer du nettoyage par le vide et de le regretter après, bien que ça ne porte pas à conséquences (sinon il y aurait une copie de sauvegarde, c'est évident).

Ainsi, dans mon tout premier post sur le présent blog, je donnais un petit teaser d'un projet personnel qui approchait de la fin et que je m'apprêtais à vous dévoiler. J'avais juste montré ceci:

Teaser



Et, comme un distrait que je suis, non content d'avoir oublié de donner suite à cette promesse je me suis permis d'éradiquer par un bon vieux rm des familles le répertoire où je conservais les photos des différentes étapes de la réalisation dudit projet, qui s'étalait sur quelques mois de temps libre trop sporadique.

Bon tant pis, vous n'aurez droit qu'au produit fini alors:



...la suite par ici...