Tag Archives: code

Je code, donc je suis

Mercredi 21 novembre, l’édition 2018 du Colloque HumanIA se tiendra à l’Agora Hydro-Québec du Complexe des sciences Pierre-Dansereau de l’UQAM dès 9h30. Dans le cadre de la semaine La France à l’UQAM, le Colloque sera suivi d’un débat sur le thème «Intelligence artificielle : l’erreur n’est-elle qu’humaine ?», dans l’après midi. J’interviendrais pour ma part dans un atelier en avant midi, sur le theme, “je code, donc je suis“. Je mets quelques liens pour alimenter la discussion,

Permuter, sans créer de variable temporaire

Je n’aime pas me faire coller par un (ancien) étudiant !… mais j’ai trouvé la solution très jolie, alors je vais en garder la trace dans mon “cahier de recherche” qu’est mon blog. La question était simple :

Comment permuter les valeurs de deux variables, sans créer de variable temporaire ?

On a ainsi deux variables, https://latex.codecogs.com/gif.latex?A et https://latex.codecogs.com/gif.latex?B, on veut les permuter : https://latex.codecogs.com/gif.latex?A doit prendre la valeur de https://latex.codecogs.com/gif.latex?B, et inversement….

> a=1
> b=2
> a
[1] 1
> b
[1] 2

Continue reading Permuter, sans créer de variable temporaire

Génération hackers ?

Je suis régulièrement effaré lorsque j’entends les parents d’ami(e)s de ma fille (la petite dernière) s’extasier que leur enfant arrive à dévérouiller “tout seul !” leur téléphone cellulaire. Le coté auto-célébration de son rejeton, je connais depuis plus d’une dizaine d’années (et je pense en avoir fait aussi ma part), mais c’est plutôt le commentaire “ah vraiment, cette génération sait tellement bien utiliser l’informatique… tu te rends compte, elle a seulement 3 ans !“.

Il serait temps de rétablir une vérité historique: je commence à me faire vieux, mais pourtant, quand j’étais à l’école primaire, on avait des cours d’informatique. Ce n’était pas comme aujourd’hui, où mes enfants ont toujours eu un ordinateur au fond de la salle (dès l’école maternelle, soit à l’age de 2 ans en France), qui servait à faire défiler des photos, ou à aller chercher des informations sur internet. De mon temps, on n’avait pas un ordinateur dans chaque classe, mais il y avait une salle informatique avec des MO5 (qui venaient de sortir). Et par informatique, j’entends par là que l’on apprenait à taper des lignes de code (on n’avait pas internet, oui, j’ai connu ces ages reculés). Ce n’était pas bien méchant: il y avait le logo, mais surtout le Basic (c’était dans le cadre du plan informatique pour tous). De manière surprenante, on était actif devant un écran, en produisant des choses !

Je me souviens avoir fait mes premiers jeux à l’age de mon fils (lui a 10 ans, mais j’étais peut-être un peu plus vieux, maintenant que je découvre les dates exactes en tapant ce billet, je vois que ma mémoire me joue des tours). Souvent, on recopiait des lignes de codes, mais quand même ! Comment se fait-il que l’aspect programmation ait été complètement enlevé des écoles, pour ne parler que d’applications ? et le plus souvent sous une forme ultra rudimentaire, pour ne pas dire mauvaise. Par exemple, je suis régulièrement effaré que mon fils n’ait pas la moindre notion de sécurité informatique (et je ne parle pas de mise en garde avant de créer une page sur Facebook… ce qui serait la moindre des choses) ! Il rentre régulièrement de l’école, m’expliquant que des copains lui ont parlé d’un nouveau site de jeux. Mais il faut s’inscrire, créer un compte, etc. L’autre jour, en discutant un peu avec lui des mots de passe, on a compris qu’il pourrait être amusant de créer un site, où les gens entreraient leur adresse électronique, et un mot de passe. Et que le mot de passe permettrait surement de se connecter sur leur adresse électronique (oui, il s’est rendu compte qu’il utilisait toujours le même mot de passe). Il pourrait alors faire des bonnes blagues en envoyant des messages à leur place ! (il a 10 ans, ses blagues sont encore relativement innocentes). On a eu une longue discussion au début de la semaine de relâche, et je me rends compte qu’il ne manque pas grand chose pour en faire un vrai hacker (j’entends par là le sens que l’on trouve sur wikipedia, “un hacker est quelqu’un qui aime comprendre le fonctionnement d’un mécanisme, afin de pouvoir le bidouiller“; il est dommage que dans l’imaginaire collectif – j’entends par là ce que l’on peut lire dans les journaux – le hacker soit aussi mal perçu, alors que c’est juste quelqu’un de curieux… la curiosité est devenu un bien mauvais défaut).

Après avoir longuement hésité (et parce que je ne trouvais pas de camps de jour qui proposait d’apprendre à faire de l’informatique), je me suis lancé: mon fils va faire du R. Lui est content car il réclame souvent à pouvoir “faire des trucs” sur l’ordinateur, et moi car j’ai l’illusion qu’il va apprendre des choses qui pourraient lui servir un jour (au moins à comprendre comment fonctionne un ordinateur). Et autant que faire se peut, j’essaye de séparer les activités familiales de ce qui pourrait s’approcher du travail. En fait, je pensais acheter python for kids (et en profiter pour découvrir un langage que j’aurais du apprendre voilà 10 ans). Mais le livre est en anglais, et mon fils n’est pas très à l’aise. Bref, je me suis lancé dans R for kids (par moi même)L’objectif était d’apprendre à faire des dessins  (un peu dans l’idée du logo je pense). De comprendre qu’un dessin était une succession de formes de base. J’ai commencé (pendant le cours d’escrime de mon fils) à taper quelques fonctions simples (carré, trait, triangle, disque, point, etc), et à coder les principales couleurs (pour qu’il les tape en français). Tout est caché dans la fonction

source("http://freakonometrics.free.fr/RforKIDZ.R")

Ensuite, on s’est lancé. Le point de départ est de faire un dessin ! Oui, c’est plus simple. Ensuite, on va définir des points, en donnant leur coordonnées à partir de la grille de fond

fond()

pour créer la grille de fond, et pour les points

A=c(0,0)
B=c(4,12)
C=c(0,12)
D=c(2,15)

On peut d’ailleurs visualiser ces points (pour vérifier qu’ils sont bien placés)

point(A)
point(B)
point(C)
point(D)

Puis on fait les figures.

carre(A,B,"gris")
polygone(C,B,D,couleur="rouge")

(dans la première version, je n’avais pas pensé faire une fonction spécifique pour les triangles) Ensuite, on rajoute un drapeau,

E=c(2,18)

pour le sommet du mat, puis pour le reste

trait(D,E,"noir",ep=2)
F=c(2,16)
point(F)
G=c(6,17)
point(G)
polygone(E,F,G,couleur="jaune")

Ce n’est pas du code, ça…. Ben, un peu quand même…. surtout quand on a vu qu’on pouvait translater une figure,

h=15
A=c(0+h,0)
B=c(4+h,12)
C=c(0+h,12)
D=c(2+h,15)
E=c(2+h,18)
carre(A,B,"gris")
polygone(C,B,D,couleur="rouge")
trait(D,E,"noir",ep=2)
F=c(2+h,16)
G=c(6+h,17)
polygone(E,F,G,couleur="jaune")

Et hop, on a deux tours.

Je pense que c’est là le cœur de la programmation: comprendre qu’il y a une forme de base, et qu’après, on ne fait que répéter. Ensuite, au centre, on a fait le mur, et on a mis les créneaux, là encore, en comprenant que c’était la même figure, translatée plusieurs fois…

A=c(4,0)
B=c(15,8)
carre(A,B,"gris")

A=c(5,8)
B=A+1
carre(A,B,"gris")

et puis on répète

A=c(7,8)
B=A+1
carre(A,B,"gris")

A=c(9,8)
B=A+1
carre(A,B,"gris")

etc…

(on a vu au passage que si on ne compte pas utiliser un point, on peut donner son nom à un autre) Enfin, pour faire le mur et la porte, on a vu qu’on avait le choix: Le plus simple (après de longues négociations discussions) a été de faire un rectangle, puis de faire un trou carré, et un cercle (en blancs).

A=c(13,8)
B=A+1
carre(A,B,"gris")

A=c(8,0)
B=c(12,4)
carre(A,B,"blanc")

C=c(10,4)
disque(C,2,"blanc")

Pas mal ? Bon, maintenant, ça me gêne un peu. Parce que je ne suis pas un bon codeur, et je vais apprendre de mauvais réflexes à mon fils (ou mes enfants, car ma fille a fini par participer, mais on verra plus tard ce qu’elle a fait).

Le plus marrant, c’est qu’on a vu comment faire un film: on a construit une voiture (assez sommaire, j’en conviens, les ingénieurs pesteront surement en voyant notre boite à chaussures avec deux roues).

dessin=function(x){
fond()
A=c(2+x,2)
B=c(6+x,4)
C=c(3+x,2)
D=c(5+x,2)
carre(A,B,"vert")
disque(C,.75,"noir")
disque(D,.75,"noir")
}

(c’est moi qui est codé la fonction, on verra ça plus en détails une prochaine fois). Et ensuite, on l’a faite se translater, de la gauche, vers la droite: on commence par taper

dessin(0)

puis

dessin(1)

et

dessin(2)

etc… en allant vite, on crée du mouvement…

Amusant, non ?

Ma fille, elle a opté pour un dessin plus traditionnel… le fameux “maison avec arbre et arc en ciel”,

Voilà ce qu’on a pu faire en quelques heures… Je pense qu’on pourrait faire mieux, et je suis ouvert à toutes suggestions: sur la façon d’apprendre à coder, sur l’interface (on utilise R-studio: on code dans la fenêtre de gauche, on utilise l’icône “run” et le dessin s’affiche à droite), sur d’éventuelles applications amusantes, ou des expériences menées par des instituteurs qui veulent apprendre les bases de l’informatique à leurs élèves. Je trouve énormément de ressources en anglais, comme le livre python for kids dont je parlais au début (ou les sites dédiés aux jeux que l’on code soi-même, en python, comme inventwithpython.com/, qui me font penser à ce que je faisais quand j’étais petit), mais je pourrais citer le scratch. Car si la France semble avoir été pionnière en 1980, je ne vois plus grand chose ces temps-ci, en français… Mais je ne sais peut-être pas bien chercher dans la communauté francophone.

Qui ne voit pas la présence du diable dans la loi ?

Je suis de plus en plus dérouté par le mélange des genres dans l’espace médiatique, de ces prétendus spécialistes qui nous expliquent des choses qu’ils ont du découvrir 10 minutes avant de commencer à taper un article. Ce matin, des éditorialistes se sentaient autoriser à fabuler sur un sondage conduit sur internet auprès de 800 personnes, et j’avoue que cela m’a agacé… J’ignore si j’ai davantage de légitimité, mais je me suis dit que la loi 78 adoptée vendredi (au Québec) pourrait être un prétexte intéressant pour écrire sur un sujet d’actualité (chose que j’hésite d’ordinaire à faire, car ce n’est pas mon métier, loin de là). Pourquoi ne pourrais-je pas, moi aussi, faire mon malin et analyser un texte de loi ? On va donc regarder cette loi dans le détail, à partir du texte en ligne sur http://profscontrelahausse.org/ (ou pour être complètement honnête, le début seulement de la loi)

L=paste("Dans la presente loi, a moins",
"que le contexte nindique",
"un sens different, on entend par:",
"association d’etudiants}}:une",
"association ou un regroupement ",
"d’associations de niveau postsecondaire",

etc

"la qualite de l’enseignement, les ",
"services requis de façon a ",
"tenir compte des circonstances particulieres",
"resultant de l’interruption ",
"de la session d’hiver de l’annee 2012 ou ",
"de la session d’ete de l’annee 2012.")

L2=substring(toupper(L),1:nchar(L),1:nchar(L))
alphabet=c("A","B","C","D","E","F","G"
,"H","I","J","K","L","M","N","O",
"P","Q","R","S","T","U","V","W","X","Y","Z")
L2=L2[L2%in%alphabet]
ML=t(matrix(L2,nc,nl))

On peut visualiser le début du texte ci-dessous (l’idée est de ne garder que les lettres, pour faire simple, mais on peut tenter plus largement en gardant la ponctuation, et les chiffres, ça ne change rien aux algorithmes que nous allons développer)

Commencons pas des trivialités: le texte de cette loi est fondamentalement inégalitaire: ce sont toujours les mêmes qui sortent gagnants, et les mêmes qui sortent perdants,

> sort(table(L))[c(1,2,3,4,5,20,21,22,23)]
L
Y   J   X   H   F   N   A   S   E
7   8  10  24  26 355 386 402 820
On retrouve ici reproduites les inégalités observées dans presque tous les textes (sauf peut être La Disparition, mais c’est une autre histoire): N, A, S et E en tête, et toujours les mêmes petites lettres qui se trouvent honteusement oubliées…

Maintenant, si on prend le temps de regarder en détail le contenu de la loi, force est de constater qu’on y voit la présence du Malin constamment ! Pour reprendre une idée de Bahye ben Asher ibn Halawa (רבינו בחיי) on peut tenter d’utiliser le code de la ThorahJulien Prévieux avait utilisé cette technique il y a quelques temps pour retrouver toute une terminologie associée aux crashs boursiers dans une page du Capital de Karl Marx, prise au hasard, ou aux paradis fiscaux dans la Richesse des Nations d’Adam Smith. Les amateurs de la théorie de Ramsey prétendront que c’est une supercherie, et ils auront probablement raison. Mais après avoir joué l’autre jour sur la recherche de schémas graphiques dans des images (en l’occurrence des rayures rouges et blanches, afin de repérer Charlie), j’ai eu envie de jouer à chercher des mots dans une matrice de lettres.

Commençons par nous donner un mot, au hasard, e.g.`
MOT="DEMON"
Le but est de voir si ce mot figure, ou pas, dans la matrice de lettre, suivant un schéma simple (c’est l’idée du code de la Thorah). Ma stratégie est ici assez simple: il faut commencer par chercher la lettre la moins présente dans la matrice, qui figure dans le mot. En fait, dans DEMON, je vais me focaliser sur les lettres du centre (en excluant la première et la dernière), i.e. DEMON
lettrelaplusrare=function(mot=MOT){
lettres=substring(mot,2:(nchar(mot)-1),
2:(nchar(mot)-1));
fL=TL[lettres];
return(names(fL)[which.min(fL)])}
rare=lettrelaplusrare()
On trouve ainsi la lettre qui va servir de base dans notre algorithme. A la rigueur, je peux faire une petite fonction qui va colorer une lettre dans la matrice,
dessinlettre=function(ltr="A",clr="yellow"){
which(L==ltr);
CLR=rep(NA,length(ML));
CLR[which(as.vector(ML)==ltr)]=clr;
dessin(ML,CLR,plt=FALSE)}
mais pour le moment, ça ne sert à rien. Dans un second temps, on regarde les lettres qui entourent la lettre la plus rare (c’est pour ça que j’ai exclus les lettres au bord, afin d’être certain d’avoir toujours une lettre avant, et une après),
lettres=substring(MOT,1:(nchar(mot)),
1:(nchar(mot)))
avant=lettres[which(lettres==rare)-1]
apres=lettres[which(lettres==rare)+1]
avant=avant[1]
apres=apres[1]
dessinlettre(rare,"yellow")
dessinlettre(avant,"green")
dessinlettre(apres,"pink")
On a ainsi trois lettres importantes: une relativement rare au centre, en jaune, une avant, en vert, et une après en rose. C’est ce qu’on peut visualiser sur le dessin ci-dessous,
Bon, ensuite on rentre dans l’algorithme, un peu lourd à mon gout: on va étudier tous les triplets possibles de ces trois lettres, en identifiants ceux pour lesquels la lettre au centre est précisément au milieu, coincée entre les deux autres lettres. C’est le principe de ce code de la Thorah. La première étape est de récupérer les coordonnées (dans la matrice) de ces trois lettres,
lrr=which(as.vector(ML)==rare)
lav=which(as.vector(ML)==avant)
lap=which(as.vector(ML)==apres) 
LIGrr=(lrr-1)%%nrow(ML)+1
COLrr=(lrr-1)%/%nrow(ML)+1
LIGav=(lav-1)%%nrow(ML)+1
COLav=(lav-1)%/%nrow(ML)+1
LIGap=(lap-1)%%nrow(ML)+1
COLap=(lap-1)%/%nrow(ML)+1
ptrr=cbind(LIGrr,COLrr)
ptav=cbind(LIGav,COLav)
ptap=cbind(LIGap,COLap)
Ensuite, on balaye l’ensemble des triplets (et ça peut être long),
pointsalignes=function(x,y,z){
((y[1]+2*(x[1]-y[1]))==z[1])&((y[2]+
2*(x[2]-y[2]))==z[2])}
LEQUEL=rep(NA,3)
for(a in 1:length(LIGrr)){
for(b in 1:length(LIGav)){
for(c in 1:length(LIGap)){
if(pointsalignes(ptrr[a,],ptav[b,],ptap[c,])==
TRUE){LEQUEL=cbind(LEQUEL,c(a,b,c))}
}}}
Parmi les triplets, on retient seulement ceux pour lesquels la lettre du milieu est précisément au centre, entre les deux autres. Enfin arrive la dernière étape pénible: regarder suivant la suite logique ce que sont les mots que l’on obtient (une fois placées ces trois lettres, la récurrence est complètement décrite). On retient alors les quintuplets correspondant au mot DEMON,
V=LEQUEL
for(k in 2:ncol(V)){
CLR=rep(NA,length(ML));
i1=ptrr[V[1,k],];
CLR[(i1[2]-1)*ncol(ML)+i1[1]]=clr;
lettres=substring(MOT,1:(nchar(mot)),
1:(nchar(mot)))
milieu=which(lettres==rare)
obtenu=ML[i1[1],i1[2]]
for(u in 1:(milieu-1)){
i2=ptav[V[2,k],]+(u-1)*(ptav[V[2,k],]-ptrr[V[1,k],]);
indice=(i2[2]-1)*ncol(ML)+i2[1]
if((i2[2]<=ncol(ML))&(i2[1]>=1)&(i2[1]<=
nrow(ML))&(i2[1]>=1)){CLR[indice]=clr;
obtenu=paste(ML[i2[1],i2[2]],obtenu,sep="")}}
for(u in (milieu+1):nchar(MOT)){
i3=ptap[V[3,k],]+(u-milieu-1)*(ptap[V[3,k],]-
ptrr[V[1,k],]);
indice=(i3[2]-1)*ncol(ML)+i3[1]
if((i3[2]<=ncol(ML))&(i3[1]>=1)&(i3[1]<=
nrow(ML))&(i3[1]>=1)){CLR[indice]=clr;
obtenu=paste(obtenu,ML[i3[1],i3[2]],sep="")}}
if(obtenu==MOT)
{print(paste(k,"  ",obtenu))}}
Reste à faire tourner cette boucle. Et ca ne manque pas, DEMON apparaît effectivement dans le texte,
On peut aller vérifier, pour ceux qui douteraient,

Coïncidence ? Peut-être…. alors tentons un autre mot, comme MALIN, qui apparait aussi,

ou alors SATAN… ce dernier apparaît huit fois dans le début du texte !

Étonnant non…. en tous les cas, je me suis bien amusé à coder ce petit algorithme, et de voir qu’il fonctionnait aussi bien ! Les amateurs de probabilités pourront se lancer dans des calculs, ou consulter quelques articles qui évoquent cette technique, comme McKay,Bar-Natan, Bar-Hillel & Kalai (2001), et tous les articles évoqués dans les références… Quant au juge qui devra se prononcer sur ma condamnation pour blasphème et pour hérésie, il va de soi que ce billet est une blague. Le diable n’existe pas ! On n’est plus au moyen-age quand même….