Défi de programmation

Ya longtemps, avec Gamo, Batchy et compagnie, on se lançait des défis de programmation sur un thème bien précis, ça donnais parfois des trucs genre « programme moi un serveur http en 2h », ou bien des défis un peu plus tendus, basés sur l'élaboration d'un algorithme un peu tordu, mais toujours très intéressant.

Vu que moi ça me manque, et qu'on avait dit un jour que l'on recommencerais, et ben voilà !

Pour ce premier défi (depuis longtemps), je vais commencer par un truc assez simple, que Gamo nous avait déjà fait découvrir : les fonctions récursives. Je n'en dit pas plus, je vous laisse chercher si vous avez besoin de plus d'informations.

Le but du jeu va être de programmer une fonction qui aura le comportement suivant :

vagues(5, 3)
Affichera :

S
SS
SSS
SSSS
SSSSS
SSSS
SSS
SS
S
SS
SSS
SSSS
SSSSS
SSSS
SSS
SS
S
SS
SSS
SSSS
SSSSS
SSSS
SSS
SS
S

Le premier argument est la hauteur des vagues (en nombre de caractères), le second argument est le nombre de vagues

Le truc, c'est que vous n'avez pas le droit d'utiliser de structures de boucles dans votre programme (et la, je vous renvois 2 paragraphes plus haut). Vous ne devez pas non plus utiliser des spécificités de votre langage qui pourraient vous aider à résoudre ce problème.

Pour les règles, y'en a pas vraiment. Vous utilisez le langage que vous voulez, il n'y a rien à gagner, et je vous encourage à partager toute la doc utile que vous trouverez. Pour le code, le mieux est de l'héberger sur des sites de collage, sur un repository (cvs, svn, hg, ce que vous voulez tant qu'on peut accéder au code facilement avec un navigateur), ou encore sur votre hébergeur préféré. En fait, ce qu'il ne faut surtout pas, c'est le poster dans les commentaires, car vous perdriez l'indentation et la chasse fixe.

Pour ma part, je vais le faire en python (et peut être aussi en perl, on verra :))

Bon alors, voila les propositions, d'abbord, celle de Sunny en ruby:

#!/usr/bin/ruby
# Vagues, de Sunny Ripert
#    implémentation ruby de http://inaps.org/journal/defiprog-1
# Sous licence WTFGL - http://sam.zoy.org/wtfpl/

class Vague
 def initialize height, count
   @maxheight, @maxcount = height.to_i, count.to_i
   raise ArgumentError, \"Height must be bigger than 2\" if @maxheight < 2
   raise ArgumentError, \"Count must be bigger than 1\" if @maxcount < 1
   @count, @height = 0, 1
   @output = \"\"
   crest
   waves
 end
 def waves
   @height = 1
   @count += 1
   wave
   waves unless @count == @maxcount
 end
 def wave
   @height += 1
   crest
   wave unless @height == @maxheight
   @height -= 1
   crest
 end
 def crest
   @h = 0
   oscillation
   @output += \"\\n\"
 end
 def oscillation
   @h += 1
   @output += \"S\"
   oscillation unless @h == @height
 end
 def to_s
   @output
 end
end

if __FILE__ == $0
 abort \"Usage: #{$0} height count\" if ARGV.size < 2
 puts Vague.new(ARGV[0], ARGV[1]) rescue puts($!)
end

Ou par ici en couleur. Ensuite, celle de Batchy, en C(kipu :))

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* waves_backend(int depth, int times) {
   char *ret = NULL ,*othret;
   if (times > 0) {
       printf(\"%s\", ret = waves_backend(depth,times-1));
   } else if (times == 0) {
       puts(\"S\");
       ret = calloc(((depth + 2) * depth - 2 ), sizeof *ret);
       strcat(ret, othret = waves_backend(depth - 1, -1));
       free(othret);
       strcat(ret, othret = waves_backend(depth - 2, -2));
       free(othret);

   } else if (depth > 0) {
       ret= calloc((((depth + 4) * (depth + 1)) / 2 + 1), sizeof *ret);

       if (times == -2)
           strcat(strcpy(ret, othret=waves_backend(-depth, -1)),\"\\n\");
       else
           strcpy(ret, othret = waves_backend(depth - 1, -3));

       free(othret);

       if (times == -2)
           strcat(ret, othret = waves_backend(depth - 1,-2));
       else
           strcat(strcat(ret, othret = waves_backend(-depth, -1)),\"\\n\");

       free(othret);

   } else if (depth == 0) {
       ret=calloc(3, sizeof *ret);
       if (times != -3)
           strcpy(ret, \"S\\n\");
   } else {
       ret=calloc(2 - depth, sizeof *ret);
       strcpy(ret, othret = waves_backend(depth + 1, -1));
       ret[-depth] = \'S\';
       free(othret);
   }
   return ret;
}

void waves(int depth, int times) {
   if (depth > 1 && times > 0)
       free(waves_backend(depth, times));
}
int main(int argc, char *argv[]) {
   if (argc < 3)
       puts(\"usage: <depth of waves> <number of waves>\");
   else
       waves(atoi(argv[1]), atoi(argv[2]));
   return 0;
}

Ou par ici en couleur. La mienne, en python :

#!/usr/bin/env python

from sys import stdout

def row(size, i=0):
   if i != size:
       stdout.write(\'S\')
       row(size, i+1)

def aWave(size, i=1, d=1):
   if i == size:
       row(i)
       stdout.write(\'\\n\')
       aWave(size, i=i-1, d=0)
   elif i==0:
       return
   elif d:
       row(i)
       stdout.write(\'\\n\')
       aWave(size, i=i+1)
   else:
       row(i)
       stdout.write(\'\\n\')
       aWave(size, i=i-1, d=0)        

def waves(size, number, i=0):
   if i != number:
       aWave(size)
       waves(size, number, i=i+1)
vagues = waves

vagues(5, 2)

Et enfin, la version de gamo, en bash, très gore :

#!/bin/sh
# !!! the script must be chmod +x !!!
# at least i think so
if [ ${#*} -lt 3 ]; then
   $0 $* $(($1 -1)) -
   exit
fi

maxc=$1; wave=$2; curr=$3; op=$4

ndisp=$(($maxc - $curr))
seq -w -s\" \" $ndisp | sed -e \'s/[0-9]*/#/g\' -e \'s/ //g\'

if [ $ndisp -eq $maxc ]; then
   op=\"+\"
elif [ $ndisp -eq 1 ]; then
   op=\"-\"; wave=$(($wave - 1))
   if [ $wave -lt 0 ]; then exit; fi
fi

. $0 $maxc $wave $(expr $curr $op 1) $op

Encore une de gamo, en C :

/* be a nazi and compile with:
* gcc -Wall -ansi -posix -pedantic cwaves.c -o toto
*
* OFC!
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void tibal(unsigned int n)
{
   if (n)
   {
       write(1, \"\\x23\", 1);
       tibal(--n);
   }
   else
       write(1, \"\\x0a\", 1);
}

unsigned char cwaves(unsigned int maxc, unsigned int wave,
                    unsigned int curr, char op)
{
   unsigned int ndisp = maxc - curr;

   /* hi2u2 :) */
   tibal(ndisp);

   if (!(ndisp ^ maxc))
         op = 1;
   else if (ndisp == 1)
   {
       op = -1;
       wave -= 1;
       
       if (!wave)
           return EXIT_SUCCESS;
   }
   cwaves(maxc, wave, curr+op, op);
   /* never happens but nazi gcc stfu with this */
   return EXIT_SUCCESS;
}


int main(int argc, char **argv)
{
   return (argc != 3)?EXIT_FAILURE:cwaves(atoi(argv[1]), atoi(argv[2]) + 1,
                                          atoi(argv[1]) - 1, -1);
}

Commentaires

Avatar de Antoine
Antoine inaps.org
le 23 décembre 2007 02:33

<strong>Bon, j'ai la flemme de migrer tous les commentaires alors voici un copier->coller :</strong>

<blockquote cite="Multiples auteurs">commentaire de webs
lifeisdead.net/
Le mardi 2 octobre 2007 à 19h23

Moi, ruby.

commentaire de TibaL
tibal.info
Le mardi 2 octobre 2007 à 19h23

Moi, C.

commentaire de Sunny
sunfox.org/
Le mardi 2 octobre 2007 à 19h26

ruby: http://toothpaste.escaline.org/code/64

commentaire de webs
lifeisdead.net/
Le mardi 2 octobre 2007 à 19h30

En fait non c'est sunny qui fait le ruby.

commentaire de Antoine
inaps.org
Le mardi 2 octobre 2007 à 19h38

Sauf que sunny il a faux la, il utilise une spécificité de ruby qui lui simplifie les choses.

(Faut vraiment que je foutte cette case à cocher pour sauver les informations quand on envois un commentaie :x)

commentaire de Sunny
sunfox.org/
Le mardi 2 octobre 2007 à 19h45

Ok, voilà sans la "spécificité" : http://toothpaste.escaline.org/code/66

commentaire de Sunny
sunfox.org/
Le mardi 2 octobre 2007 à 20h3

Ajouté à mon dépot sous http://code.sunfox.org/vagues/trunk/?vagues.rb

Vive le ruby \o/

commentaire de BatchyX
Le mardi 2 octobre 2007 à 21h28

en Ckipu : http://toothpaste.escaline.org/code/67

attention code crade : prendre des gants.

commentaire de gamo
Le mercredi 3 octobre 2007 à 21h29

en bash version moche, qui peux l'etre encore plus (j'ai mon idee mais je suis bourré): http://pong.polio.be/~matth/vague.sh.txt

commentaire de gamo
www.polio.be
Le jeudi 4 octobre 2007 à 13h26

encore du laid, mais en C cette fois :p
http://pong.polio.be/~matth/cwaves.c.txt

commentaire de TibaL
tibal.info
Le jeudi 4 octobre 2007 à 23h33

Mon code en C: http://toothpaste.escaline.org/code/68
Je finis par le poster mais toujours sans comprendre pourquoi ça plante avec des grandes valeurs, par exemple amplitude=10 et 99999 vagues.
Ce n'est pas lié aux types des variables en tout cas...

commentaire de TibaL
tibal.info
Le vendredi 5 octobre 2007 à 21h16

Nouvelle version en C++ : http://toothpaste.escaline.org/code/69
ça m'a fait gagner une ligne de code \o/ (potentiellement deux, mais je n'ai pas encore réussi)
Le bug précédent persiste toujours, probablement à cause d'une récursion trop profonde (call stack trop petite ?).

commentaire de BatchyX
Le samedi 6 octobre 2007 à 10h59

celui de gamo plante aussi avec des grandes valeurs, c'est juste un dépassement de stack ;)
mais le mien il plante pas :p (enfin si, avec 180000 vagues de 10 de hauteurs ... je laisse l'exercice au lecteur pour augmenter cette limite, c'est pas compliqué)
</blockquote>

Avatar de Araen
Araen
le 21 février 2008 19:21

Et voilà le mien en python :
http://pastebin.com/f2f21931e

J'ai pas mis de vérification, c'est juste pour l'algorithme ;)

Avatar de JeromeJ
JeromeJ www.olissea.com
le 01 mars 2008 13:27

Et en PHP ?

function wave($height, $nb_wave, $str = 'S')
{
for($i = 0; $i &lt; $nb_wave; $i++)
{
for($a = 1, $count = ($height*2)-1; $a &lt; $count; $a++)
{
if($a &lt;= $height) echo str_repeat($str, $a);
else echo str_repeat($str, ($count-$a+1));

echo '',"\n";
}
}
}

wave(6, 3);

Avatar de JeromeJ
JeromeJ www.olissea.com
le 01 mars 2008 13:28

Zut ;O on voit pas l'identation ni le br ... Désolé.

Avatar de BatchyX
BatchyX
le 01 mars 2008 18:12

Ouais mais ça va pas du tout !
on à dit pas de boucle ni de fonction préfaites du langage. exit donc les for(;;) et les str_repeat()

Avatar de BatchyX
BatchyX
le 01 mars 2008 18:17

et pareil, pas le droit au chaine*nombre du python/ruby.

Avatar de wumzi
wumzi www.wumzi.info
le 22 avril 2010 23:46

Encore un autre en Python (quel magnifique language pour se concentrer sur la logique pure ...)

http://ideone.com/weF01

Laisser un commentaire
:
:

Optionnel.

:

Ne sera pas publiée, elle est utile pour les Gravatars et la modération des commentaires.

:

Vous pouvez utiliser ces marqueurs : a, strong, em, pre, blockquote, abbr, acronym, et code. Les sauts de lignes et les liens sont automatiquement convertis.

:

Ce test permet de vérifier que vous n'êtes pas un (salaud de) robot de spam.


J'utilise Escaline 
!