Journal Créer un livre dont vous êtes le héros avec des outils libres + question sur les regex

Posté par  .
Étiquettes : aucune
0
17
juil.
2007
Bonjour,

Ce journal est à la fois la présentation d'un petit projet, et une question qui aurait dû figurer dans le forum...

je suis en train de développer un genre de modèle pour réaliser des "livres-jeux" type "Livres dont vous êtes le héros" à partir de txt2tags. Cela permet à partir d'une même source d'exporter le jeu en version html et latex avec un joli rendu (avec liens hypertextes). La syntaxe est super simple, et pas du tout obtrusive. En fait les paragraphes sont délimités par des == chapitre ==, et la référence à ce paragraphe se fait uniquement avec les numéros en fin de ligne.

La page de présentation se trouve ici :

http://anamnese.online.fr/site2/txt2cyoa/txt2cyoa.html

Seulement, ce n'est pas ultra pratique à visualiser une histoire comme cela. J'ai pensé qu'avec graphviz on pouvait faire quelques merveilles supplémentaires, à savoir générer un organigramme directement à partir des chapitres. Je n'ai pas réussi à le faire automatiquement et proprement à partir de txt2tags, par contre à coup de grep j'arrive à avoir une base, et avec quelques ajustements, on peut générer le graphique :

http://anamnese.online.fr/site2/txt2cyoa/txt2cyoa_graph.png

Alors voilà, ma question est de savoir s'il est possible en ligne de commande, en python, en perl ou ce que vous voulez, à modifier le dernier fichier que j'arrive à avoir de sorte qu'il puisse être utilisé directement avec graphviz.

J'obtiens :

digraph G {
1->
8;9;
6;
2->
6;
3;
7;
3->
6;
5;
4;
7;
4->
6;
5;
3;
5->
6;
3;
2;
6->
5;
3;
7->
8->
9->
}


et j'ai besoin de :


digraph G {
1->8;
1->9;
1->6;
2->6;
2->3;
2->7;
3->6;
3->5;
3->4;
3->7;
4->6;
4->5;
4->3;
5->6;
5->3;
5->2;
6->5;
6->3;
}


En fait la mission est "simplement" de pouvoir prendre la première ligne contenant la séquence "nombre->", la mémoriser, et la coller avant chaque ligne qui se termine par un ; jusqu'à une nouvelle séquence nombre-> qui remplace la première et se colle dans les lignes du dessous etc.

Est-ce que cela est possible (sans doute avec sed) ? Comment feriez-vous ? j'ai cherché sur les forums et sur internet, mais je n'ai rien trouvé d'approchant.

Merci d'avance.
  • # html ..

    Posté par  . Évalué à 0.

    ca peut pas se faire en html ?
    • [^] # Re: html ..

      Posté par  . Évalué à 1.

      tu veux dire en php ?

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

      • [^] # Re: html ..

        Posté par  . Évalué à 3.

        il faudrait que l'on m'explique ce qu'il entendait par "en html"...

        Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

  • # Un perleux va surement nous faire un truc en une ligne...

    Posté par  . Évalué à 10.

    Mais voilà la version Python:
    import sys
    
    input = sys.stdin.read()
    
    i = "0"
    for line in input.splitlines():
    	if "->" in line:
    		i = line.split("->")[0]
    	elif ';' in line:
    		for j in line.split(";"):
    			if j.strip():
    				print "%s->%s"% (i, j)
    	else:
    		print line
    
    • [^] # Re: Un perleux va surement nous faire un truc en une ligne...

      Posté par  . Évalué à 3.

      SUPER !

      Merci beaucoup, c'est tout à fait ce que j'attendais (en 25 minutes top chrono c'est quand même fort d'avoir une réponse aussi vite), cela fonctionne très bien. Je viens de faire la mise à jour du truc, cela fait un peu code frankenstein, mais je ne suis pas développeur :)

      Merci encore. En plus cela va pouvoir m'aider pour d'autres types de codage dont j'aurai sans doute besoin par la suite.

      Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

  • # Perl !

    Posté par  (site web personnel) . Évalué à 4.


    #!/usr/bin/perl
    use strict;
    my $fichier=$ARGV[0];
    open (FILE,"<$fichier") || die "ARGH : $!\n";
    my $page;
    while(){
      chomp $_;
      if($_=~/->/){
          $page=$_;
      }elsif($_=~m/;/){
          @_=split ";",$_;
          foreach(@_){
          print "$page$_;\n";
          }
      }else{
          print "$_\n";
      }
    }
    close(FILE);
    • [^] # Re: Perl !

      Posté par  . Évalué à 5.

      Pas assez marrant, on veut une expression régulière en une ligne ;)
      (oui, je suis dessus depuis 1 heure maintenant ;))
      • [^] # Re: Perl !

        Posté par  . Évalué à 10.

        A défaut d'une expression régulière, voilà la version gawk

        gawk '/->/ { z=$0} /[0-9]+[^->]/ {print z$0}' FIC.txt

        C'est simple et efficace. Comme quoi, c'est utile les "vieux" outils Unix :)
        • [^] # Re: Perl !

          Posté par  . Évalué à 1.

          Sympathique et astucieux (et pertinenté).
          Par contre, ça ne gère pas le cas
          1->
          8;9;
          Est-ce un manque grave?
          • [^] # Re: Perl !

            Posté par  . Évalué à 2.

            pas trop pour ma part. En fait la règle c'est de toujours terminer une ligne de choix par la valeur de ce choix (numéro de chapitre). Comme cela n'avait pas été fait dans la première ligne, du coup cela ne fonctionne plus comme prévu, mais si on écrit une aventure avec dans l'esprit d'avoir le graphique à la fin, et que l'on respecte la règle, pas de pb.

            Enfin, il doit être possible d'ajouter un filtre supplémentaire pour ajouter un retour à la ligne là où il faut (je peux le faire avec txt2tags à un niveau plus haut...)

            Mais pour utiliser la version gawk, il faut que je vérifie si cela supprime bien les lignes avec un nombre et -> sans rien à la fin...

            Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

          • [^] # Re: Perl !

            Posté par  . Évalué à 3.

            Si oui, c'est facilement adaptable :


            gawk -F ';' '/->/ { z=$0} /[0-9]+[^->]/ { for (i=1; i < NF; i++) { print z$i";" } }' FIC.txt
            • [^] # Re: Perl !

              Posté par  . Évalué à 5.

              Zut, j'ai sorti ma version trop tard... (J'ai du ouvrir la doc pour me souvenir du NF :s)
              awk -F';' '!/[0-9]/{print $0}/->/{a=$0}/[0-9]+[^->]/{for(x=1;x<NF;x++)print a$x";"}' src.txt

              Enfin, elle à l'avantage de pas supprimer les entêtes, contrairement à la tienne. :)
      • [^] # Re: Perl !

        Posté par  . Évalué à 10.

        Ah la la, les petits jeunes. Toujours à nous sortir une enclume pour un truc qui prends même pas une ligne:

        cat myfile | perl -pe 'if(m/^(\d+)->/) { $i=$1; $_=""; } else { s/(\d+);\n?/$i->$1;\n/g; }'

        perl -p fait la boucle et le print tout seul pour tout le contenu du fichier passée en entrée.

        perl -e execute le programme passé sur la ligne de commande

        Le if cherche un nombre suivit de '->' et le conserve dans la variable $i; il supprime la sortie en vidant $_

        Le else ajoute "$i->" devant les chiffres et ajoute un saut de ligne.

        Voila, ça ne m'a pas pris 10 minutes.
        • [^] # Re: Perl !

          Posté par  . Évalué à 4.

          UUOC!

          (ah la la, les petits jeunes...)
    • [^] # Re: Perdu !

      Posté par  . Évalué à 10.

      Cette fois ci, c'est clair. On a la réponse en Python 23 minutes après que le journal ait été posté, et la réponse en Perl aura mis 66 minutes à arriver.

      De quoi on peut facilement déduire que Python est 3 fois plus efficace que Perl.
      • [^] # Re: Perdu !

        Posté par  (site web personnel) . Évalué à 9.

        Ou que les mecs qui font du python n'ont rien à foutre que de trainer sur dlfp alors que les perliens bossent encore ;-)
        • [^] # Re: Perdu !

          Posté par  . Évalué à 8.

          ou que les pythoneux sont au chômage et que les perleux on un taf, eux...

          --->[]
      • [^] # Re: Perdu !

        Posté par  (site web personnel) . Évalué à 4.

        #!/usr/bin/ruby

        module Game
        def Game.parse(filename)
        fd = open(filename, 'r')
        h, k = {}, ""
        fd.each do |l|
        case l.chomp!
        when /^[0-9]+->$/
        k = l.delete("->")
        h[k] ||= []
        when /^([0-9]+;)+$/
        l.split(";").each { |i| h[k] << i }
        end
        end
        return h
        end
        def Game.render(filename)
        parse(filename).each do |key,value|
        value.each {|item| puts "#{key}->#{item};" }
        end
        end
        end

        Game::render("foobar.graph")

        je proteste, j'étais en train de boire une bière devant un film!

        PS: je sais pas comment on affiche du code proprement, frappez pas s'il vous plait
        PPS: je garantis pas que ça soit 100% fool proof ou que je vais pas me faire incendier par des rubyistes plus aguéris que moi
        • [^] # Re: Perdu !

          Posté par  . Évalué à 3.

          merci de ta contribution, ainsi que celles de tous les autres. Pour le moment je garde celle en python, mais si la version gawk fait exactement la même chose, cela simplifiera un peu, je vais tester. La version perl est un peu plus confuse que python, mais merci quand même. Pour java c'est intéressant de voir comment on peut le faire, mais je vais me contenter de qque chose de plus simple...

          Pour afficher le code, tu tapes autour : <blockquote> ton texte </blockquote>



          Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

  • # Les regexp ramollissent le cerveau

    Posté par  (site web personnel) . Évalué à 2.

    Pourquoi utiliser des regexp alors qu'un simple parser suffit (oui je sais faire ça en java c'est utiliser une bombe atomique pour tuer une mouche :-)
    import java.io.File;
    import java.io.FileReader;
    import java.io.IOException;
    
    public class Digraph
    {
        public static void main(String[] args)
        {
    	if (args.length != 1) {
    	    System.out.println("usage: java Diagraph <graph_file>");
    	    System.exit(-1);
    	}
    	File f = new File(args[0]);
    	try {
    	    Digraph graph = new Digraph(f);
    	} catch (IOException e) {
    	    e.printStackTrace();
    	    System.exit(-2);
    	}
        }
    
        Digraph(File f) throws IOException
        {
    	FileReader reader = new FileReader(f);
    	int key = 0;
    	int cur = 0;
    	for (;;) {
    	    int c = reader.read();
    	    if (c == -1)
    		break;
    	    if (Character.isWhitespace((char)c))
    		continue;
    	    switch (c) {
    	    case '1':
    	    case '2':
    	    case '3':
    	    case '4':
    	    case '5':
    	    case '6':
    	    case '7':
    	    case '8':
    	    case '9':
    	    case '0':
    		cur = 10 * cur + (c - '0');
    		break;
    	    case '-':
    		break;
    	    case '>':
    		key = cur;
    		cur = 0;
    		break;
    	    case ';':
    		System.out.printf("%d->%d\n", key, cur);
    		cur = 0;
    		break;
    	    default:
    		throw new IOException(String.format("Unexpected char: %c", c));
    	    }
    	}
        }
    }
    
  • # Golf

    Posté par  . Évalué à 5.

    Une solution en 132 caractères, nullement digne d'un golfeur expérimenté et ne reprenant pas les lignes digraph G { et } pour gagner un peu... J'essairai de faire mieux au réveil cet aprem (ou pas).


    chomp&&/(\d+)->/?$c=$1:/(\d|;)+/m&&push(@{$r[$c]},split(/;/,$_))while<>;for$i(1..$c){print$i.'->'.$a.";\n"while $a=shift(@{$r[$i]})}
    • [^] # Re: Golf

      Posté par  . Évalué à 3.

      $ perl -ne '/[{}]/?print:/\d+->/||print"$&$_"'fichier

      Si on veut bien s'autoriser à ne pas sortir le bloc digraph {}, on peut simplifier en:
      $ perl -ne '/[{}]/||/\d+->/||print"$&$_"' fichier

      Si le fichier d'entrée joue le jeu et ne contient même pas ledit bloc, c'est la fête:
      $ grep -v '[{}]' fichier |
      > perl -ne '/\d+->/||print"$&$_"'

      Merci à l'exemple awk pour l'inspiration. :-)
  • # Pdf offline

    Posté par  . Évalué à 2.

    Tu as prévu de faire une version pdf pour l'impression ? C'est à dire de remplacer les liens hypertextes par des ref. de pages (avec latex ça va pas être bien compliqué).

    Autre demande, si tu peux proposer la même chose en export A5/livret (c'est à dire qu'il y a qu'à predre le paquet de feuilles de l'imprimante, et replier le tout pour faire un livre), çà serait super :) (là ça doit être plus compliqué)
    • [^] # Re: Pdf offline

      Posté par  (site web personnel) . Évalué à 2.

      > (là ça doit être plus compliqué)
      Non, tu sors un dvi et tu le malmène un coup avec les outils qui vont bien*, puis tu le convertis en pdf.

      * j'ai plus les noms en tête, je peux chercher pour les curieux.
      • [^] # Re: Pdf offline

        Posté par  . Évalué à 2.

        les références de page ne sont pas nécessaire pour la version papier. Les liens hypertextes pointent vers les chapitres tel qu'ils doivent apparaître, tout comme les livres-jeux traditionnels.

        Je vais essayer de faire de nouveaux gabarits tex, notamment pour un format A5. Pour la mise en page, je ne sais pas s'il est possible avec tex d'avoir automatiquement des livrets comme dans openoffice (sinon on peut toujours faire du copier / coller depuis html vers ooo, mais c'est pas pareil quand même au point de vue rendu).

        Je n'utilise pas de dvi intermédiaire ou de ps, car c'est généré avec pdflatex, par contre je pense que pdftk peut faire ce genre d'opérations de recollage des pages.

        Only wimps use tape backup: real men just upload their important stuff on megaupload, and let the rest of the world ~~mirror~~ link to it

    • [^] # Re: Pdf offline

      Posté par  (site web personnel) . Évalué à 2.


      Autre demande, si tu peux proposer la même chose en export A5/livret


      Ou alors utiliser le paquetage booklet pour LaTeX (et utiliser pdflatex pour générer le PDF). Je n'ai plus la doc en tête car je n'ai utilisé il y a de nombreuses années, mais je me souviens que c'était relativement simple.

      http://www.ctan.org/tex-archive/macros/latex/contrib/booklet(...)

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.