IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Coder en JavaScript avec seulement six caractères
Un tutoriel de Sylvain Pollet-Villard

Le , par vermine

0PARTAGES

4  0 


Sylvain Pollet-Villard s'ennuyait sûrement le jour où il eut l'idée saugrenue de coder du JavaScript avec le moins de caractères possibles. Et pourtant, il l'a fait ! Il nous explique les différentes étapes de sa démarche qui aboutit à la rédaction d'un compilateur.

Coder en JavaScript avec seulement six caractères

N'hésitez pas à lui faire part de vos commentaires et remarques sur cette drôle de machinerie barbare.

Une erreur dans cette actualité ? Signalez-nous-la !

Avatar de OPi
Membre actif https://www.developpez.com
Le 10/07/2013 à 11:15
Pour Python cela me semble impossible, cela ne peut se faire qu'avec des langages à typage faible.

J'ai généré automatiquement les codes bien parenthésés d'une certaine longueur qui sont évaluées correctement.
Code : Sélectionner tout
+!![]
et
Code : Sélectionner tout
+!+[]
donnent aussi le nombre 1.

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
object		6	[[[]]] 
object		4	[[]] 
object		2	[] 
undefined	undefined	6	[][[]] 
string		5	[]+[] 
string	false	6	[]+![] 
object	0	5	[+[]] 
object	false	5	[![]] 
object	true	6	[!+[]] 
object	true	6	[!![]] 
number	0	5	+[[]] 
number	0	3	+[] 
string	0	6	+[]+[] 
number	NaN	6	+[![]] 
number	1	5	+!+[] 
number	1	5	+!![] 
boolean	false	5	![[]] 
boolean	false	3	![] 
string	false	6	![]+[] 
boolean	true	6	!+[[]] 
boolean	true	4	!+[] 
boolean	true	4	!![]
Plus de résultats dans les fichiers attachés.

Code : Sélectionner tout
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
var CHARS = ['[', ']', '+', '!', '(', ')'];  /* changer ce tableau pour utiliser d'autres caractères */ 
 
 
 
var NB_CHARS = CHARS.length; 
 
var BALANCED_CHARS = {}; 
var CLOSE_CHARS = []; 
if ( CHARS.indexOf('[') >= 0 ) { 
    BALANCED_CHARS['['] = ']'; 
    CLOSE_CHARS.push(']'); 
} 
if ( CHARS.indexOf('(') >= 0 ) { 
    BALANCED_CHARS['('] = ')'; 
    CLOSE_CHARS.push(')'); 
} 
if ( CHARS.indexOf('{') >= 0 ) { 
    BALANCED_CHARS['{'] = '}'; 
    CLOSE_CHARS.push('}'); 
} 
 
var results = {}; 
 
 
 
/* 
  Renvoie true 
  si s est bien parenthésée, 
  false sinon. 
*/ 
function balanced(s) { 
    'use strict'; 
 
    var s_LENGTH = s.length; 
 
    var stack = []; 
 
    var i; 
    var c; 
 
    for (i = 0; i < s_LENGTH; i++) { 
        c = s[i]; 
        if ( c in BALANCED_CHARS ) { 
            stack.push(c); 
        } 
        else if ( CLOSE_CHARS.indexOf(c) >= 0 ) { 
            if ( BALANCED_CHARS[stack.pop()] !== c ) { 
                return false; 
            } 
        } 
    } 
 
    return (stack.length === 0); 
} 
 
 
/* 
  Parcourt récursivement les chaînes jusqu'à une longueur num, 
  tente de les évaluer 
  et affiche les résultats non encore rencontrés ou déjà rencontrés mais au moins aussi long. 
 */ 
function build_and_try_string(s, num) { 
    'use strict'; 
 
    if ( num > 0 ) { 
        var i; 
        var c; 
 
        for (i = 0; i < NB_CHARS; i++) { 
            c = CHARS[i]; 
 
            try_string(s + c); 
            build_and_try_string(s + c, num - 1); 
        } 
    } 
} 
 
 
/* 
  Affiche s 
*/ 
function display(s) { 
    try {            // dans un navigateur 
        document.write(s + '\n'); 
    } 
    catch ( err ) {  // avec Rhino 
        print(s); 
    } 
} 
 
 
/* 
  Tente d'évaluer s. 
  Si l'évaluation s'est bien passée 
  et que le résultat n'a pas encore été obtenu ou a déjà été obtenu avec une chaîne au moins aussi longue, 
  alors affiche le résultat. 
 
  BORD: ajoute l'éventuel élément affiché à results 
*/ 
function try_string(s) { 
    'use strict'; 
 
    if ( balanced(s) ) { 
        var v; 
 
        try { 
            v = eval(s); 
        } 
        catch ( err ) { 
            return; 
        } 
 
        var k = [typeof v, v]; 
 
        if ( !(k in results) || (s.length <= results[k]) ) { 
            results[k] = s.length; 
            display((typeof v) + '\t' + v + '\t' + s.length + '\t' + s); 
        } 
    } 
} 
 
 
 
/* Main */ 
build_and_try_string('', 6);
4  0 
Avatar de Kaamo
Membre émérite https://www.developpez.com
Le 08/07/2013 à 10:08
Pour information, voici le sujet de la réflexion.

Sylvain, as-tu pu échanger avec le créateur de JSFuck ?
1  0 
Avatar de anykeyh
Membre confirmé https://www.developpez.com
Le 09/07/2013 à 11:35
Bravo bon boulot!

En plus de la considération ludique, je trouve que c'est très instructif ce genre d'exploit!
1  0 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 02/06/2016 à 0:16
Good news everyone !

Je vous disais dans cet article publié il y a presque trois ans qu'il serait peut-être possible de descendre à 5 caractères. Une nouvelle piste est apparue avec la norme ECMAScript 6 et la fonction Array.prototype.find ! En effet, nous disposons de toutes les lettres de "find" grâce à undefined.

Cela permet donc de récupérer une fonction sans avoir besoin du caractère "!".

Code : Sélectionner tout
1
2
Array.prototype.find === [][[[]+[][+[]]][+[]][++[++[++[++[[]][+[]]][+[]]][+[]]][+[]]]+[[]+[][+[]]][+[]][++[++[++[++[++[[]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[]+[][+[]]][+[]][++[[]][+[]]]+[[]+[][+[]]][+[]][++[++[[]][+[]]][+[]]]]
et de la même façon que dans le chapitre V, le c, le o et le v, mais aussi le caractère espace ainsi que les crochets, les accolades et les parenthèses.

C'est un gros bond en avant, mais je n'ai pas réussi pour le moment à aller plus loin avec les 3 caractères +[]. En effet, les lettres C O V ne nous débloquent pas vraiment. Les seules nouvelles fonctions accessibles grâce à ces lettres sont #String.concat ou #Array.concat.

Pour aller plus loin, la piste la plus sérieuse serait de réussir à obtenir la valeur null, ce qui nous donnerait la lettre L puis la fonction #Function.call. A partir de là, tout est possible Mais aucune fonction accessible dans la norme ECMAScript actuelle ne nous renvoie null
1  0 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 08/07/2013 à 13:39
Je lui ai lâché un message sur le github du projet, mais pas de réponse pour le moment

Si on voulait vraiment pousser la réflexion jusqu'au bout, il faudrait travailler l'optimisation de toute la table de caractères, puis comparer la taille du code généré avec ou sans l'usage de String.fromCharCode

Mais je crois que ça dépasse le seuil d'intérêt que l'on puisse légitimement prêter à ce problème
0  0 
Avatar de rambc
Membre chevronné https://www.developpez.com
Le 09/07/2013 à 20:01
Très rigolo !!!

Existe-t-il un équivalent pour le langage Python ou est-ce propre à JS ?
0  0 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 10/07/2013 à 9:20
Je ne connais pas assez bien le Python pour répondre, mais je suis sûr que d'autres s'amuseraient beaucoup à faire la même chose sur d'autres langages

Citation Envoyé par Quentin de Serres-Justiniac

Bonjour,

Après m'être délecté de la lecture de cet article : http://sylvainpv.developpez.com/tuto...-6-caracteres/ qui m'a fait sourire bon nombre de fois.
Je m'interrogeais sur l'utilité d'une telle approche. Hormis le côté ludique et la prouesse technique, est-ce que cela a un intérêt ?
Une fois compressé le code est-il plus léger ? Vu le peu de caractères différent, je me dis qu'un bon GZ fera sans doute des ravages dans la taille du code. Ceci dit l'extrême lourdeur de l'écriture pourrait je pense alourdir de façon bien trop considérable le code pour que même minifié et gzippé ce soit encore trop lourd.
(Je laisse de côté volontairement la portabilité).

Bonne journée et merci pour cet article fun à lire le matin en arrivant au bureau
En effet hormis le côté ludique, il n'y a strictement aucun intérêt pratique. Comme je le dis en avant-propos : "Si le défi ne présente pas d'intérêt en soi, il permet en revanche de manière très ludique d'appréhender divers aspects du langage sous un angle tout à fait inhabituel"

Le code généré est largement plus long que l'original, comme tu as pu le constater si tu as essayé le compilateur. Eventuellement on pourrait s'y intéresser à des fins d'obfuscation de code extrême, mais je ne pense pas que ce soit la meilleure approche.
0  0 
Avatar de elias551
Membre du Club https://www.developpez.com
Le 10/07/2013 à 17:06
Très instructif tout ça!

En Perl aussi on peut utiliser les regex à outrance, ce qui peut donner ça
0  0 
Avatar de SylvainPV
Rédacteur/Modérateur https://www.developpez.com
Le 05/06/2016 à 22:02
Voici une présentation en anglais parcourant de manière plus synthétique tout le cheminement pour arriver au compilateur:
http://slides.com/sylvainpv/xchars-js/

Le compilateur a également été mis à jour pour fonctionner avec Chrome, Firefox et Edge dans leurs dernières versions.

Dernière chose, une démonstration du 1K chess de Óscar Toledo G.convertie via 6chars.js est jouable ici : http://syllab.fr/projets/experiments/sixcharsjs/nanochess.html

Regardez la source
0  0