Une machine de Turing

Une machine de Turing est une représentation mathématique d'un ordinateur. Elle dispose d'un ruban (tape), sur lequel elle peut se déplacer vers la gauche ou vers la droite, lire et écrire un caractère.
Pour représenter les chiffres, cette machine utilise la base 1. Pour le chiffre 0, elle place un barre (1) sur le ruban, pour représenter le chiffre 2, elle en place 3...

Malgré sa simplicité, cette machine est capable de calculer toutes les fonctions récursives.

Petit exemple :

Un exemple très simple est la fonction Zéro. C'est une fonction constante, qui pour n'importe quel nombre renvoie 0. Rappelons-nous qu'avec notre machine le 0 s'écrit avec une barre (1).

Si nous prenons le ruban contenant le chiffre 4 :
11111000000000000
Nous devrions donc obtenir :
10000000000000000

Analysons le programme :
q0 1 D q1 # On conserve le 1er 1 : pour faire 0
q1 1 0 q2 # Suppression des 1 inutiles
q2 0 D q1

q1 0 0 q3 # Retour à la position initiale
q3 0 G q3

Une machine de Turing dispose d'un algorithme très simple, celui-ci a même été reproduit mécaniquement ou optiquement !
Une instruction se compose de 4 parties :
L'état initial, la condition, l'action et l'état final.
Par exemple pour la première : q0 1 D q1
Au début nous sommes toujours à l'état 0. Le premier élément du ruban est 1.
Notre machine va dont recherche un instruction commençant par q0 1, ensuite elle va exécuter l'instruction contenue dans la seconde partie de l'instruction.
Ici : D q1 : Elle doit donc avancer vers la Droite sur le ruban et passer à l'état q1.
Elle va maintenant recherche une instruction correspondante à l'état q1 et qui a comme condition l'élément courant du ruban : ici 1 et nous exécutons l'action 0 (remplacer l'élément courant du ruban par 0) et passer à l'état q2.

Pour résumer, les actions dont elle dispose sont :
G : Aller à gauche
D : Aller à droite
1 : Écrire un 1
0 : Écrire un 0
et parfois :
* : Écrire une * pour délimiter deux nombres par exemple

Une machine de Turing en Python :

Cette machine est capable de gérer un nombre infini d'état.


# -*- coding: utf-8 -*-

#

# uTuring

#

# Copyright (c) 2010 Amaury GRAILLAT

# Licensed under the GNU GPL license.

# See http://www.gnu.org/licenses/gpl.html

#               amoweb.fr 

#

# File exemple :

# # Zero function                              You can comment a line with #

# q0 1 0 q1       {Stat} {Condition} {Action (1, 0, *, L or R)} {Final stat}

# q1 0 D q0

# q0 0 1 q2

# 

# =1111000000000000000000:0                ={tape}:{Initial stat (optional)}

#



import os

INDD = 0 ; COND = 1 ; ACTN = 2 ; INDF = 3

ruban = [] ; instr = []

k = 0   # position sur le ruban

q = '0' # état



# Trouve l'instruction correspondant à la condition et 

def searchInstruction(q,k) :

	# print "searchInstruction(%s,%s)"%(q,k)

	for i in instr :

		if i[INDD] == q and i[COND] == ruban[k] :

			return i

	return [0,0,0,0]

	

def monospace(str) :

	str = str.replace("\t", " ");

	while str.count("  ") > 0 :

		str = str.replace("  ", " ");

	return str



if __name__ == '__main__' :

	print("Welcome to uTurning : ")



	# Charge le programme depuis le fichier :

	with open("program.txt") as program :

		for instruction in program :

			# Charge le ruban

			if instruction[0:1] == "=" :

				# Partie donnée

				for s in instruction :

					if s == ':' :

						break

					elif s != '\n' and s != '=' :

						ruban.append(s)

				# Position d'origine (facultative)

				if len(instruction.split(':')) > 1 :

					k = int(instruction.split(':')[1])

			# Fin du fichier :

			elif instruction[0:3] == "EOF" :

				break

			# Charge une instruction

			elif instruction != '\n' and instruction[0:1] != "#":

				instruction = monospace(instruction);

				if len(instruction.split(' ')) > 3 :

					qStrI = instruction.split(' ')[0]

					qStrF = instruction.split(' ')[3]

					instr.append([qStrI[1:len(qStrI)], instruction.split(' ')[1],

					instruction.split(' ')[2], qStrF[1:len(qStrF)-1]])

	# Exceptions :

	if len(ruban) == 0 :

		print "TAPE missing : example : =11100000:0"

		exit()

	if len(instr) == 0 :

		print "Instructions missing : example : q0 1 0 q2 "

		exit()



	# Exécution des instructions :

	curInst = searchInstruction(q, k)

	while curInst != [0,0,0,0] :

		# Affiche le ruban :

		print (''.join(ruban)) + " (q" + q + ")"

		print " "*k + "^"



		# Interprête les instructions :

		if curInst[ACTN] == 'D' or curInst[ACTN] == 'R' :

			k = k + 1

		elif curInst[ACTN] == 'G' or curInst[ACTN] == 'L':

			k = k - 1

		elif k < 0 :

			print "Warning ! Out of range : k = -1 ---> k = 0"

		else :

			ruban[k] = curInst[ACTN]



		# Nouvel état 

		q = curInst[INDF]



		curInst = searchInstruction(q, k)

# Affiche le ruban final :

print (''.join(ruban)) + " (q" + q + ")"

print " "*k + "^"

Et quelques exemples (à copier coller dans un fichier program.txt à coté du programme python) :


# Fonction successeur :

q0 1 D q0

q0 0 1 qa

qa 1 G qa

qa 0 D q2

=1111100000000000:0





EOF ----------------------------

# Couples d'entiers :

# Suppression :

q0 1 D q0

Q0 * * Q1

q1 * 0 q2

q1 1 0 q2

q2 0 D q1



Q1 0 0 Q3

Q3 0 G Q3

Q3 1 1 Q4

Q4 1 G Q4

Q4 0 D Q5



=111*1111000000000000000000

Un service de partage de Blocnote en ligne - Les Sources

Suite aux demandes de Tom et Lewo, je met aujourd'hui en ligne le code de mon Simple Black Board en Ajax (PHP et fichiers textes).
Il permet, par l'intermédiaire d'un lien unique de partager un texte et de permettre la modification et la visualisation des modifications en temps réel par les visiteurs.
Le code est largement inspiré d'un tutoriel du SdZ.

Demo
Télécharger sources (GNU GPL)

Plus d'infos sur Simple Black Board

Théâtre : Une tournée, une vraie.

Imaginez-vous, un jeudi à 13h, dans un petit village de la Drôme (Sud-Est). Il ne faisait pas très chaud, le temps semblait alors idéal pour faire les 6h de route qui nous séparaient de l'Indre-et-Loire (Nord-Ouest). Sur le trajet nous étions huit membres de La Chaumière d'EDGUAR, une récente (mais pas sans expérience) association théâtrale, qui interprète Les souvenirs se font la malle.

Montrésor, vue du rempart du château
Montrésor, vue du rampart du château. (Crédit : Nathan)

Nous sommes arrivés, assez tôt à Montrésor, c'était la seconde fois que je m'y rendais. J'aime beaucoup cette ville, son historique, son architecture. Le vendredi matin nous avons pu visiter l'église et le château.
À 14 nous avons garé le camion devant la salle des fêtes d'Orbigny, après 3h d'installation et quelques tours de tarots les premières personnes arrivent. Ça fait plaisir de savoir qu'il y a du monde, alors que le spectacle n'est pas connu dans la région. Très vite, on entend les rires, les applaudissements.

Je n'avais jamais imaginé faire un jour une tournée, une vraie : une loin.
Je découvre tout les ans de nouvelles salles des fêtes avec La Chaumière d'EDGUAR et Le petit théâtre des Mathurins et j'avais déjà fait 3 jours de spectacle de suite, mais jamais dans 3 salles différentes. Nous avons dû déplacer une scène, faire des choix, trouver des solutions dans des lieux inconnus et très différents : des salles des fêtes et un château (à Orbigny, Loché-sur-Indrois et Chemillé-sur-Indrois). C'était de l'adaptation, de la vraie.

Nous avons rencontré plein de monde. Mise à part la fatigue, tout était génial : autant à l'Indrois qu'à l'inverse.

MissWhite and The Drunken Piano ! l'exemple même d'un HipHop ouvert.

Vous connaissez le HipHop ? Je ne connaissez que quelques classiques commerciaux avant hier soir : lors d'un concert.
Contrairement à ce que beaucoup pense, le HipHop est un style très ouvert, où peuvent se mélange plusieurs autres styles.
Hier soir j'ai découvert 3 groupes : MissWhite, Smooth et Hocus Pocus

C'était très intéressant de comparer les interprétations différentes du HipHop qu'avaient ces trois groupes :

Smooth, nous montrait un HipHop très rock avec des paroles chantées, et un accompagnement piano "carré". La basse très présente et le synthétiseur faisaient allusions au funk.

Hocus Pocus semblait influencé par la dance, avec les vents et les cuivres et le jazz dans les improvisations, notamment au piano.

MissWhite aux frontières du jazz (avec le piano et le saxophone) et du jazz vocal, certaines musiques sont des arrangements de musiques classiques (Chopin par exemple).

Les mises en scène de ces deux derniers groupe ont été soignées : Un show millimétré pour Hocus Pocus, et une mise en scène très théâtrale pour MissWhite.


Présentation de MissWhite

Anti-XSS : Méthode de vérification de contenu normalisé

Ceux qui développent des sites Internet, ou plus simplement les personnes qui suivent l'actualité on déjà entendu parler de Cross-site scripting (abrégé XSS... vous aussi vous cherchez le X dans Cross ?).
Le principe est simple : arriver à faire exécuter un script non prévus par une application. Par exemple un pirate souhaitant aider les personnes agées qui auraient du mal à retenir leur mot passe... (!)

La faille la plus courante est l'affichage directe d'une variable entrée par l'utilisateur. Le PHP étant un langage "à la volé", l'entrée utilisateur peut être interprétée comme du code PHP ou JavaScript et être exécuté.
Dans la plus part des cas un htmlspecialchars($_GET['var 1']) est suffisant.
Ce problème réside d'une loi qui peut paraitre radicale, mais qui se révèle très adapté à l'informatique : Tout ce qui n'est pas prévus est potentiellement dangereux.
Rien ne nous prouve qu'un utilisateur ne va jamais écris un chiffre au lieu d'une lettre, ou pire, un script au lieu d'un simple texte.
Dans cet article nous allons voir plusieurs méthode automatiques de vérification du contenu des variables. Elles ont pour but de remplacer les méthodes manuelles qui sont sources d'oublis.

Méthode manuelle fonctionnelle :

Cette méthode est relativement courante, elle nécessite de "passer" toutes les variables dans des fonctions de vérifications. Il faut donc créer une fonction pour chaque type : checkInt(), checkHtml(), checkUrl()...

Par exemple pour checkInt() : nous pouvons utiliser le code :

checkInt($entier) {
  return intval($entier);
}
ou avec une expression régulière :
checkInt($entier) {
  if(preg_match('/^[0-9]+$/', $entier))
    return $entier;
  else
    return 0;
}
Dans ces deux cas l'entrée d'un valeur autre qu'un chiffre retournera 0.

Méthode singulière :

Cette méthode est la plus simple à mettre en place car elle ne nécessite pas la modification du code. Cependant le script ne doit pas contenir deux variables de même nom contenant des choses différentes.
Cette méthode est dite singulière car les règles sont fixées individuellement pour chaque variable.

Exemple : Ce code doit être appelé en début de programme :

# Tableau de règles
$type_var = array(
  'id' => '/^[0-9]+$/',
  'level' => '/^[0-9]{4}$/',
  'name' => '/^[a-zA-Z]+$/'
);

# Vérification des variables reçues en $_GET :
foreach ($_GET as $key => $value)
  if(!preg_match($type_var[$key],$value) || isset($type_var[$key])) 
    unset($_GET[$key]);
Dans cette solution nous vérifions si les variables sont bien présentes dans le tableau et si leur contenu correspond bien à la règle. Dans le cas échéant nous supprimons les variables.
Cette solution permet de ne pas oublier de variable, mais peut cependant devenir très lourde avec un grand nombre de variables.

Méthode typée :

Cette méthode part d'un constat simple : il n'est pas toujours possible de répertorier toutes les variables. Nous allons donc mettre un place un système de typage complet.
Adaptons l'exemple précédent avec cette méthode :

# Tableau de règles
$type_var = array(
  '_int' => '/^[0-9]+$/',
  '_4int' => '/^[0-9]{4}$/',
  '_alpha' => '/^[a-zA-Z]+$/'
);

# Vérification des variables reçues en $_GET :
foreach ($_GET as $key => $value)
  if(!preg_match($type_var[strrchr($key,"_")],$value))
    unset($_GET[$key]);
Avec cette solution les variables de l'exemple précédent id, level, name deviendraient id_int, level_4int, name_alpha.
Cette méthode nous oblige à renommer toutes la variables du projet mais peut s'avérer terriblement efficace. Ici nous supprimons les variables non valides, mais rien ne nous empêche de stocker dans notre tableau une valeur de remplacement par défaut. Il serait aussi possible de mélanger la méthode singulier avec la méthode typée. Cela permettrait de traiter à part des variables sans que le type ne soit dans son nom.

Méthode typée : Le cas particulier de l'URL :

Un URL est un cas particulier de notre Méthode typée, car il devient difficile de définir une regex pour une URL quand elle contient des paramètres. Nous allons donc analyser toutes les variables de l'URL, à l'aide de notre tableau. Nous ajoutons un type _url très peu restrictif qui fait un pré-tri.

$_GET["url_url"] = "http://amoweb.fr/index.php?i_int=31d2&c_alpha=abcde&b_int=332";

# Tableau de règles
$type_var = array(
  '_int' => '/^[0-9]+$/',
  '_4int' => '/^[0-9]{4}$/',
  '_alpha' => '/^[a-zA-Z]+$/',
  '_url' => '/^http(s)?:\/\/[-\/.\w?&]{0,64}$/i'

);

# Vérification d'une url :

# Extraction de la partie URL :
$url = explode("?",urldecode($_GET['url_url']), 2);
$_GET['url_url'] = $url[0] . "?";

# Vérifie chaque variable passée en paramètre
foreach (explode("&",$url[1]) as $param) {
	$varGET = explode("=",$param);
	# On fabrique l'URL avec les paramètre valides : dont le contenu correspond au type
	if(preg_match($type_var[strrchr($varGET[0],"_")],$varGET[1]))
		$_GET['url_url'] .= $varGET[0] . "=" . $varGET[1] . "&";
}

# Supprimer le caractère final : soit '?' soit '&'
$_GET["url_url"] = substr($_GET["url_url"], 0, -1);

# Et voilà le travail :
echo $_GET["url_url"]; # http://amoweb.fr/index.php?c_alpha=abcde&b_int=332