Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

toujours moins !

1 view
Skip to first unread message

ulis

unread,
Jul 14, 2006, 4:52:03 AM7/14/06
to
Voilà : on m'a nommé programmeur Tcl et mon patron me demande de
raccourcir le programme suivant qu'il trouve trop long.
J'Y COMPRENDS RIEN !
Il faut garder le paramètre p et les deux couleurs, mais c'est tout.
Il faut aussi :
- utiliser le moins de constantes possible,
- diminuer le nombre de commandes (c'est les mots en bleu sous
l'éditeur).
COMMENT JE PEUX FAIRE ?

package require Tk
set p 2
array set color {0 #abcdef 1 #fedcba}
set max [expr {2 << $p}]
set s [list]
foreach i {0 1} \
{
set img($i) [image create photo -width 10 -height 10]
$img($i) put $color($i) -to 0 0 10 10
}
for {set i 0} {$i < $max} {incr i} \
{
for {set j 0} {$j < $max} {incr j} \
{
button .($i:$j) -image $img(0) -command ($i:$j) -bd 0
grid .($i:$j) -row $i -column $j
bind .($i:$j) <ButtonPress-3> undo
proc ($i:$j) {} \
{
foreach {i j} [split [string range [info level 0] 1 end-1] :]
break
for {set ii [expr {$i - 1}]} {$ii <= [expr {$i + 1}]} {incr ii}
\
{
for {set jj [expr {$j - 1}]} {$jj <= [expr {$j + 1}]} {incr
jj} \
{ if {!($ii & $::max || $jj & $::max)} { ($ii!$jj) } }
}
lappend ::s ($i:$j)
}
proc ($i!$j) {} \
{
foreach {i j} [split [string range [info level 0] 1 end-1] !]
break
set n [expr {([.($i:$j) cget -image] == $::img(1)) ^ 1}]
.($i:$j) config -image $::img($n)
}
}
}
}
for {set n 0} {$n < $max} {incr n} \
{
set i [expr {int(rand() * $max)}]
set j [expr {int(rand() * $max)}]
($i!$j)
}
proc undo {} \
{
set n [llength $::s]
if {$n > 0} \
{
[lindex $::s end]
set ::s [lrange $::s 0 end-2]
}
}

un désespéré

ulis

unread,
Jul 14, 2006, 7:58:18 AM7/14/06
to
Le code est mal parenthésé, il parait !
Voilà une autre version. Mais on ne sait pas quelles horreurs se
tapissent dedans.

complètement désespéré

stephan...@yahoo.fr

unread,
Jul 15, 2006, 7:57:41 AM7/15/06
to
Bonjour Maurice,

Il s'agit d'un jeu que je connais pour y avoir joué
sur un ZX81 (ça date:-) A l'origine c'était paru dans un
magazine Jeux&Stratégies.

Il y a une grille (matrice) de cases noires ou blanches,
remplie aléatoirement.
Le but est que toutes les cases soient de la même couleur.
Mais ça se corse là, car le seul moyen d'y parvenir
est de cliquer sur une case, ce qui a pour effet
de changer la couleur (inverser) d'un bloc 3x3
dont le centre est la case cliquée.

En plus, le jeu est très dur et peut prendre sérieusement
la tête.
Pour ton patron, tu peux essayer de refactoriser le code
en créant de petites procédures spécialisées.
Le principal problème que je vois dans ce code
est l'abondance de boucles imbriquées.

Salutations,

Stéphane

ulis

unread,
Jul 15, 2006, 8:58:21 AM7/15/06
to
> Pour ton patron, tu peux essayer de refactoriser le code
> en créant de petites procédures spécialisées.
> Le principal problème que je vois dans ce code
> est l'abondance de boucles imbriquées.

Merci Stephane.
Pour l'instant, dès que j'essaye de simplifier quelque chose ça
rajoute des instructions !

Eric Hassold

unread,
Jul 15, 2006, 7:47:31 PM7/15/06
to
ulis wrote :

> Pour l'instant, dès que j'essaye de simplifier quelque chose ça
> rajoute des instructions !
>

C'est vraiment contradictoire? La simplicite est-elle toujours
inversement proportionnelle au nombre d'instruction ou de lignes? En
jetant un coup d'oeil aux gagnants de l'IOCCC, categorie "Best One Liner
Program", j'ai tendance a penser le contraire ;-)

http://www.ioccc.org/winners.html

Bon, mais c'est vrai, l'exercice est toujours distrayant, autant a
ecrire qu'a dechiffrer.

Eric


ulis

unread,
Jul 16, 2006, 12:12:50 PM7/16/06
to
> C'est vraiment contradictoire? La simplicite est-elle toujours
> inversement proportionnelle au nombre d'instruction ou de lignes?

En tout cas moins il y a de commandes et moins il y a de bug.
Et un programme sans commandes est le seul dont on soit sûr.
(bon, il ne fait pas forcément grand chose...)

ulis

Kroc

unread,
Jul 17, 2006, 9:08:37 AM7/17/06
to
package require Tk
set p 2
set s {}

foreach color {#fedcba #abcdef} {
image create photo $color -width 10 -height 10
$color put $color -to 0 0 10 10
}

proc do {W} {
foreach "x y" [split [string range $W 1 end] :] {}
for {set i [expr {$x - 1}]} {$i <= [expr {$x + 1}]} {incr i} {
for {set j [expr {$y - 1}]} {$j <= [expr {$y + 1}]} {incr j} {
if {![catch ".$i:$j cget -image" image] && $image eq
"#fedcba"} {
.$i:$j configure -image "#abcdef"
} else {
.$i:$j configure -image "#fedcba"
}
}
}
lappend ::s $W
}

proc undo {} {
if {[llength $::s]} {
do [lindex $::s end]


set ::s [lrange $::s 0 end-2]
}
}

for {set i 0} {$i < [expr {2 << $p}]} {incr i} {
for {set j 0} {$j < [expr {2 << $p}]} {incr j} {
grid [button .$i:$j -image $color -command [list do .$i:$j] \
-bd 0] -row $i -column $j
bind .$i:$j <ButtonPress-3> undo
}
}

--
David Zolli - Kroc

Kroc

unread,
Jul 17, 2006, 10:59:18 AM7/17/06
to
Arghh, le nul ! C'était pas bon !

Voilà le bon :

package require Tk
set p 2
set s {}
foreach color {#fedcba #abcdef} {
image create photo $color -width 10 -height 10
$color put $color -to 0 0 10 10
}

proc do {W} {
foreach "x y" [split [string range $W 1 end] :] {}
for {set i [expr {$x - 1}]} {$i <= [expr {$x + 1}]} {incr i} {
for {set j [expr {$y - 1}]} {$j <= [expr {$y + 1}]} {incr j} {

if {[winfo exists .$i:$j]} {
switch [.$i:$j cget -image] {


"#fedcba" {.$i:$j configure -image "#abcdef"}

"#abcdef" {.$i:$j configure -image "#fedcba"}

Kroc

unread,
Jul 17, 2006, 11:18:33 AM7/17/06
to
C'est hors sujet, mais le jeu est plus intéressant si on construit la
grille comme ça :

for {set i 0} {$i < [expr {2 << $p}]} {incr i} {
for {set j 0} {$j < [expr {2 << $p}]} {incr j} {

if {rand() > .5} {set I "#abcdef"} {set I "#fedcba"}
grid [button .$i:$j -image $I -command [list do .$i:$j] \

ulis

unread,
Jul 17, 2006, 2:50:49 PM7/17/06
to

> Voilà le bon :

Merci Kroc de venir à mon secours.
Ton script a l'air bougrement intéressant mais mon patron (si tu
savais ce que c'est qu'un patron) râle :
- il y a des constantes dupliquées (il veut le moins de constantes
possibles),
- et il manque l'initialisation (la boucle de randomisation avant la
proc undo).

En tout cas, bravo ! tu as l'air d'avoir pigé comment il marche. Et tu
vas peut-être me sauver.

ulis qui reprend espoir

Kroc

unread,
Jul 18, 2006, 3:48:55 AM7/18/06
to
Bon, je suis pas sûr que ça rende le truc plus clair mais voilà ce
que ça donne en virant le maximum de constantes (attention : beurk
inside) :

package require Tk
set p 2
set s {}

foreach c {#abcdef #fedcba} {
[image create photo [llength [image names]] -width 10 -height 10]\
put $c -to 0 0 10 10
}

proc do {W} {
foreach "x y" [split [string range $W 1 end] :] {}
for {set i [expr {$x - 1}]} {$i <= [expr {$x + 1}]} {incr i} {
for {set j [expr {$y - 1}]} {$j <= [expr {$y + 1}]} {incr j} {
if {[winfo exists .$i:$j]} {

.$i:$j configure -image [expr {![.$i:$j cget -image]}]
}
}
}
lappend ::s $W
}

proc undo {} {
if {[llength $::s]} {
do [lindex $::s end]
set ::s [lrange $::s 0 end-2]
}
}

for {set i 0} {$i < [expr {2 << $p}]} {incr i} {
for {set j 0} {$j < [expr {2 << $p}]} {incr j} {

grid [button .$i:$j -image [expr int(round(rand()))]\

Kroc

unread,
Jul 18, 2006, 8:30:53 AM7/18/06
to
On a joué à ce jeu hier soir ma femme et moi et il me semble bien
qu'il ne soit pas toujours possible de tout mettre de la même couleur
lorsque la grille fait [expr 2<<2]x[expr 2<<2] cases (8x8 pour les
humains). Par contre ça m'à l'air plus faisable avec 9x9 cases.

Quelqu'un peut confirmer ou infirmer cette impression ?

Jerome

unread,
Jul 18, 2006, 9:25:25 AM7/18/06
to
Si il n'y a aucun pb.
xxxxxxxx
oxxoxxox
xxxxxxxx
oxxoxxox
xxxxxxxx
xxxxxxxx
oxxoxxox
xxxxxxxx

o represente les cases a cocher.

Kroc a écrit :

Kroc

unread,
Jul 18, 2006, 9:46:30 AM7/18/06
to
Jerome a écrit :

> Si il n'y a aucun pb.
> xxxxxxxx
> oxxoxxox
> xxxxxxxx
> oxxoxxox
> xxxxxxxx
> xxxxxxxx
> oxxoxxox
> xxxxxxxx
>
> o represente les cases a cocher.

Une solution unique pour une grille générée aléatoirement !! c'est
une martinguale ? ;-)

Blague à part, ce que je voudrais savoir c'est si c'est TOUJOURS
possible avec une grille de 8x8, pas seulement possible dans certains
cas.

Kroc

unread,
Jul 18, 2006, 12:17:22 PM7/18/06
to
Juste pour le fun : la proc do avec une seule boucle "for" :

proc do {W} {
foreach "x y" [split [string range $W 1 end] :] {}

for {set a [expr {8*atan(1)}]} {$a > 0} {set a [expr
{$a-(atan(1))}]} {
set i [expr {round($x + cos($a))}]
set j [expr {round($y + sin($a))}]


if {[winfo exists .$i:$j]} {
.$i:$j configure -image [expr {![.$i:$j cget -image]}]
}
}

.$x:$y configure -image [expr {![.$x:$y cget -image]}]
lappend ::s $W
}

--
David Zolli - Kroc

Kroc

unread,
Jul 19, 2006, 6:02:45 AM7/19/06
to
Kroc a écrit :

Ben alors Maurice : pas de commentaire ? C'est toujours pas bon ou ça
te laisse sans voix ? ;-)

ulis

unread,
Jul 19, 2006, 7:15:12 AM7/19/06
to
> Ben alors Maurice : pas de commentaire ? C'est toujours pas bon ou ça
> te laisse sans voix ? ;-)

Laisse moi le temps de compter, sacrebleu !

- ton code en fait autant,
- il définit bien p et les deux couleurs (bon on va faire comme si)
- il n'utilise pas d'autre constante (..., comme l'autre, quoi)
- il a 44 commandes en bleu alors que l'autre en a 59

Tu as donc réussi à faire une économie de plus de 20%
(bon, foreach ... break remplacé par foreach ... {}, c'est facile,
mais valable)

Bravo ! Tu as fait un véritable exploit.
Je pense que mon patron voudrait t'embaucher s'il savait.

ulis qui se sent revivre :-)

Kroc

unread,
Jul 19, 2006, 7:48:20 AM7/19/06
to
ulis a écrit :

> > Ben alors Maurice : pas de commentaire ? C'est toujours pas bon ou ça
> > te laisse sans voix ? ;-)
>
> Laisse moi le temps de compter, sacrebleu !
>
> - ton code en fait autant,
> - il définit bien p et les deux couleurs (bon on va faire comme si)
> - il n'utilise pas d'autre constante (..., comme l'autre, quoi)
> - il a 44 commandes en bleu alors que l'autre en a 59
>
> Tu as donc réussi à faire une économie de plus de 20%
> (bon, foreach ... break remplacé par foreach ... {}, c'est facile,
> mais valable)
>
> Bravo ! Tu as fait un véritable exploit.

Youhou !! :-) J'ai gagné !

D'un autre côté c'est pas vraiment (voire vraiment pas) le genre de
code à montrer aux débutants ou à prendre en exemple. C'est un grand
fou ton "patron" ! ;-)

david cobac

unread,
Jul 20, 2006, 7:29:14 AM7/20/06
to
"ulis" <mauric...@gmail.com> a écrit :
>[...]

> set max [expr {2 << $p}]
>[...]

Tiens, c'est intéressant...je connaissais pas ce genre de choses.
en regardant http://wfr.tcl.tk/expr
on (enfin je) apprend pas grand-chose sur cette affaire.
En testant avec tkcon, il me semble donc que
expr {$n << $p} remplace expr {pow(2,$p)*$n}
Si je dis pas de bêtises, il s'agit donc d'une sorte de décalage de
bits.
Par contre je ne comprends pas l'autre opérateur : >>

Mes questions :
- pourquoi utiliser dans le script : 2 << $p plutôt que : 1 << $p+1 ?
- pourquoi "éviter" : pow(2,$p+1) ?
- à quoi ça sert (question qui tue) typiquement ?
- c'est quoi >> alors ?

--
cordialement
david cobac

Merci à toi , O grand Ulis, toi qui a su vaincre tant d'épreuves au
cours de ton long voyage dans les profondeurs de Tcl...
(je suis en forme, ce soir !)
-+- vincent v in fr.comp.lang.tcl -+-

david cobac

unread,
Jul 20, 2006, 7:45:56 AM7/20/06
to
david cobac <davidno....@free.fr> a écrit :

>expr {$n << $p} remplace expr {pow(2,$p)*$n}

oups enfin expr {int(pow(2,$p)*$n)}

--
cordialement
david cobac

<david z> Serait-ce là la manifestation d'une envie irrépressible
d'essayer OS X ?
<ulis> non, non.
C'est que mon i-book est un béta.
pardon, mon i-book est déjà en beta.
-+- fr.comp.lang.tcl -+-

ulis

unread,
Jul 20, 2006, 12:11:40 PM7/20/06
to

> Mes questions :
> - pourquoi utiliser dans le script : 2 << $p plutôt que : 1 << $p+1 ?

On gagne peut-être un cycle d'exécution (au prix du CPU, c'est pas
grand chose)

> - pourquoi "éviter" : pow(2,$p+1) ?

on passe d'un ordre d'exponentiation (un gros sous-programme) à un
ordre de décalage (une instruction)
(au prix du CPU, c'est un peu plus)

> - à quoi ça sert (question qui tue) typiquement ?

heu ???
Quel est le sujet de "à quoi ça sert"
Les ordres de décalages ? Bin à décaler des bits. Ca permet
d'optimiser certaines opérations couteuses sur les nombres. Les
exponentiations par des multiples de 2 par exemple.

> - c'est quoi >> alors ?

Décalage à droite
Pour les profs de maths :
8 >> 2 :=: 8 /2^2

> Merci à toi , O grand Ulis, toi qui a su vaincre tant d'épreuves au
> cours de ton long voyage dans les profondeurs de Tcl...
> (je suis en forme, ce soir !)
> -+- vincent v in fr.comp.lang.tcl -+-

de rien ;-)

Xavier Garreau

unread,
Jul 20, 2006, 12:38:00 PM7/20/06
to
Bonjour,

> Tiens, c'est intéressant...je connaissais pas ce genre de choses.
> en regardant http://wfr.tcl.tk/expr
> on (enfin je) apprend pas grand-chose sur cette affaire.
> En testant avec tkcon, il me semble donc que

> expr {$n << $p} remplace expr {pow(2,$p)*$n}

> Si je dis pas de bêtises, il s'agit donc d'une sorte de décalage de
> bits.
> Par contre je ne comprends pas l'autre opérateur : >>
>
> Mes questions :
> - pourquoi utiliser dans le script : 2 << $p plutôt que : 1 << $p+1 ?

Parce que ça va plus vite

> - pourquoi "éviter" : pow(2,$p+1) ?

Parce que ça va moins vite

> - à quoi ça sert (question qui tue) typiquement ?

- à multiplier et diviser vite par 2
- à retourner les octets dans les mots pour passer du big au little endian
- à mettre une tripotée de flags (0 ou 1) dans une même variable le flag
n étant retrouvable par f = (var >> n) & 1 et activable via var = (f <<
n) | var on peut même transformer ça en va et vient en utilisant un XOR
à la place du OR.
- A obscurcir le code quand ce n'est pas nécessaire de l'optimiser à e
point :)

Exemples parlant:

3 >> 2 ça donne 0 : 00000000
3 >> 1 ça donne 1 : 00000001
3 s'écrit en binaire 00000011
3 << 1 ça donne 6 : 00000110
3 << 2 ça donne 12: 00001100

on "tire" d'un côté ou de l'autre pour déplacer un bit. Mais alors,
comment est on sûr que c'est un 0 qui arrive ? Parce que le monde est
bien fait maintenant, mais ça n'a pas toujours été le cas.

Les vieux barbus valident ça avec un masque.
01111111 pour >> 1

et
11111110 pour << 1

Donc pour être sûr on doit/devrait écrire
resultat = (depart >> 1) & 0x7f
resultat = (depart >> 2) & 0x3f
resultat = (depart >> 8) & 0x0f
resultat = (depart << 1) & 0xf7
resultat = (depart << 2) & 0xf3
resultat = (depart << 8) & 0xf0

par exemple.


> - c'est quoi >> alors ?
>

Pareil dans l'autre sens.

a+
--
Xavier Garreau
http://www.xgarreau.org/

0 new messages