Affichage des articles dont le libellé est fortran. Afficher tous les articles
Affichage des articles dont le libellé est fortran. Afficher tous les articles

dimanche 30 mars 2008

Jeu de Nim en Fortran

Vous connaissez peut-être le jeu de Nim sous le nom de "jeu des allumettes"... Version Frotran 90 "sale" ("Goto statement considered harmfull", non respect des normes actuelles...) en mode console. Au passage, je teste l'outil de conversion html de (g)Vim (f*ck it ça passe pas...)... Got a problem homie ? Just tell me (give my money and buy my medecine...). Version collée chez Pastie pour plus de lisibilité (lignes trop longues, etc...) : goto ICI.

Ze code :
(compilé avec GFortran (fortran 90) sous Windows)


Program Jeu_de_Nim
IMPLICIT NONE

integer :: nbre_allum, ordre, choix, scorePC, scoreHumain, nb_parties, i, aleas
logical :: PC_first, tournoi


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! BIENVENUE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

print*, "!!!!!!!!!!!!!!!"
print*, "JEU DE NIM v2.0"
print*, "!!!!!!!!!!!!!!!"
print*, "Bienvenue dans ce petit jeu de Nim."

print*, "A chaque tour, le joueur ou le PC doivent prendre 1, 2 ou 3 allumettes."
print*, "Celui qui prend la derniere allumette a perdu. Bonne chance."
print*, " "

scorePC = 0
scoreHumain = 0
tournoi = .FALSE.

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! MENU

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
111 print*, "Entrez votre choix :"
print*, "[0] : Nouvelle Partie"
print*, "[1] : Nouveau Tournoi"
print*, "[2] : Afficher Scores"

print*, "[3] : Reinitialiser les Scores"
print*, "[4] : Quitter"
read*, choix

SELECT CASE (choix)
CASE (0)
GOTO 222
CASE (1)
tournoi = .TRUE.
scorePC = 0
scoreHumain = 0
11 print*, "Tournoi en combien de parties ?"

read*, nb_parties
if (nb_parties < 1) then
print*, "Tssss... Trop drole..."
GOTO 11
end if

aleas = 2*rand()

PC_first = .TRUE.
IF (aleas == 1) PC_first = .FALSE.
i = 0
10 i = i+1
print*, "PARTIE numero : ", i
call Afficher_scores(scorePC, scoreHumain)
IF (i > nb_parties) then
call Afficher_scores(scorePC, scoreHumain)
if (scorePC > scoreHumain) print*, "LE PC GAGNE LE TOURNOI !!!"

if (scorePC == scoreHumain) print*, "EGALITE !!! INCROYABLE !!!"
if (scorePC < scoreHumain) print*, "VOUS GAGNEZ LE TOURNOI !!! BRAVO !!!"
GOTO 111
END IF


nbre_allum = 50*rand() + 1
PC_first = .NOT.PC_first
GOTO 223

CASE (2)
call Afficher_scores(scorePC, scoreHumain)
GOTO 111

CASE (3)
scorePC = 0
scoreHumain = 0
GOTO 111

CASE (4)
GOTO 666

CASE DEFAULT

print*, "Mauvais choooooooooooix......"
GOTO 111

END SELECT

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! PARTIE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

222 print*, "Combien d'allumettes pour la partie ? (0 pour un nombre au hasard)"
read*, nbre_allum
if (nbre_allum == 0) nbre_allum = 50*rand()+1
if (nbre_allum < 0) then
print*, "Hummmmmm... Pas beaucoup ca..."
GOTO 222
end if
print*, "Qui joue en premier ?"

print*, "[1] : PC"
print*, "[2] : Humain"
print*, "[3] : Au hasard"
read*, ordre

SELECT CASE (ordre)
CASE (1)
PC_first = .TRUE.
print*, "Le PC commence."

CASE (2)
PC_first = .FALSE.
print*, "L'humain commence."
CASE (3)
aleas = 2*rand()
PC_first = .TRUE.
IF (aleas > 1) PC_first = .FALSE.
CASE DEFAULT

PC_first = .TRUE.
print*, "Apprends a taper cono !"
print*, "Du coup le PC commence..."
END SELECT

223 IF (PC_first) THEN

do while (nbre_allum > 0)
call Tour_de_jeu_PC(nbre_allum,scoreHumain)
IF (nbre_allum > 0) call Tour_de_jeu_Humain(nbre_allum,scorePC)
end do
ELSE
do while (nbre_allum > 0)
call Tour_de_jeu_Humain(nbre_allum,scorePC)
IF (nbre_allum > 0) call Tour_de_jeu_PC(nbre_allum,scoreHumain)
end do
END IF

IF (tournoi) GOTO 10

GOTO 111

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! EXIT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
666 print*, "MERCI, A BIENTOT !"

End Program Jeu_de_Nim

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! AFFICHAGE DES SCORES
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine Afficher_scores(scPC, scHuman)
integer, intent(in) :: scPC, scHuman

print*, "!!!!! SCORE !!!!!"

print*, "PC : ", scPC
print*, "Humain : ", scHuman

End Subroutine Afficher_scores

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! TOUR PC
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine Tour_de_jeu_PC(nb_al, scHuman)
integer, intent(inout) :: nb_al, scHuman
integer :: reste, prise

print*, "Il y a ", nb_al, "allumettes."

reste = MOD(nb_al,4)

if (nb_al == 1) then
prise = 1
else
SELECT CASE (reste)
CASE (1)
prise = 3*rand()+1
CASE (2)
prise = 1
CASE (3)
prise = 2
CASE (0)
prise = 3
CASE DEFAULT

print*, "Erreur : module inconsistant"
print*, "Module = ", reste
STOP
END SELECT
end if

nb_al = nb_al - prise
print*, "Le PC prend ", prise, " allumettes."

print*, "Il reste : ", nb_al, "allumettes."

if (nb_al == 0) then
print*, "VOUS AVEZ GAGNE !!!!! FELICITATIONS !!!!"
scHuman = scHuman + 1
end if

End Subroutine Tour_de_jeu_PC


!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! TOUR HUMAIN
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Subroutine Tour_de_jeu_Humain(nb_al, scPC)
integer, intent(inout) :: nb_al, scPC
integer :: prise

print*, "Il y a ", nb_al, "allumettes."

print*, "Combien souhaitez vous en prendre ? (1, 2 ou 3)"
999 read*, prise

if ((prise > 3).OR.(prise < 1).OR.(prise > nb_al)) then
print*, "Nombre saisi incorrect : veuillez recommencer."
GOTO 999
end if

nb_al = nb_al - prise
print*, "Vous avez pris ", prise, " allumettes."

print*, "Il reste : ", nb_al, "allumettes."

if (nb_al == 0) then
print*, "VOUS AVEZ PERDU !!!!!"
scPC = scPC + 1
end if

End Subroutine Tour_de_jeu_Humain

mardi 19 février 2008

Et maintenant, quel langage ?

Les habitués de forums de programmation pour débutants (SDZ ?) devraient avoir souri en lisant ce titre... (En effet, ce type de forum voit apparaître avec une fréquence de 2 à 10 par semaine des sujet portant un titre approché de ça : "Quel language choisire svp URGENT ?" le plus souvent).

Blague à part, la question n'est pas idiote. Loin de là.
Quel langage apprendre ?

Des langages !
Beaucoup !

Il y a beaucoup de langages. De plus en plus même (note : je vais parler ici des "vrais langages" de programmation, c'est à dire, à mon sens, ceux qui sont Turing-complet ; pas du HTML, LaTeX, XML ou autres...).

Lesquels sont généralistes ? La plupart.
Lesquels sont spécialisés ou orientés vers une utilisation précise ? La plupart aussi !
Je m'explique : Fortran permet de tout faire (à condition d'être courageux) mais n'a que peu d'intérêt en dehors du domaine scientifique. Ruby est généraliste, mais est surtout employé pour des applications web (Rails...). Python permet de faire de "vrais" programmes mais sera surtout utilisé (dans le monde pro) pour du scripting d'appoint. On cherche encore Ada ailleurs que dans de l'embarqué et le Javascript ailleurs que dans des applis web côté client... Et pourtant, dans l'absolu, tous permettent de faire la même chose.

Les généralistes et les familles

Cela dit, il existe quelques langages qui sont utilisés (utilisables ?) pour à peu près tout : le C++ et le Java. Pas de chance pour eux (ou pour moi !), je ne les apprécie pas outre mesure. Sans être allergique au C++ que j'ai déjà utilisé en milieu professionnel, je trouve qu'ils sont assez proches et assez lourds (j'ai déjà le Fortran à la maison, merci !) : je reconnais sans problème leurs qualités respectives, mais ils ne conviennent pas, à mon sens, pour un usage domestique/éducatif/récréatif. De plus il ne recèlent pas ou peu de concepts nouveaux pour moi (même si ça ne me ferait pas de mal de revoir la gestion des pointeurs et références en C++ et deux, trois petites choses...).

Dans le même ordre d'idée, je pourrais me mettre au Python. Mais comme il est très proche de Ruby, à quoi bon ? Me taper les différences de syntaxe et de convention pour faire les mêmes choses qu'en Ruby mais en Python ? Pas assez rentable à mon goût ! Je pense, ou plutôt espère, que connaître un langage dans une "catégorie" facilite et accélère l'apprentissage des langages proches, en cas de nécessité. Par exemple pour Ruby : Python, Perl, Groovy, Smalltalk...

Coder, pourquoi ?
Coder plus pour gagner plus...

Car si je code, ce n'est pas que pour le plaisir.

C'est vrai qu'après des débuts difficiles, je me suis mis à apprécier de plus en plus la programmation, pour pas mal de raisons. D'abord pour l'aspect mathématique assez fort que j'y retrouve. Ensuite pour le côté "Lego" : il y a un aspect "architectural" dans la construction d'un programme, des contraintes mais aussi une grande liberté devant son éditeur de texte (un peu comme face aux briques), et une fois terminé on peut "jouer avec" son programme. Enfin, c'est un monde riche en "concepts" liés à l'image que l'on (l'homme et/ou la machine) se fait d'un problème et de sa résolution.

Mais la programmation, c'est aussi une partie importante de mon métier (ingénieur modélisation - bon, ok, pas en ce moment, mais je vais trouver ^^). Et dans ce contexte, à mon niveau, il n'est pas question de choix. On travaille avec le(s) langage(s) qu'on nous donne. Et c'est là que ça se gatte... Dans le domaine de la simulation et analyse numérique, sont surtout utilisés le Fortran et le C++, que je maîtrise "relativement" bien. Les informations glanées sur le web, au cours d'entretiens, etc... ont mis en lumière d'autres "technologies" possibles : Matlab, VisualBasic, C et Ada principalement.
  • Je pourrais me mettre au Matlab mais c'est pas gratuit, même s'il existe SciLab dans le genre...
  • L'environnement VisualBasic, malgré tout le mal que j'en pense, a été installé sur ma bécane... moins d'une heure. Déjà, les IDE m'insupportent, alors quand on ajoute un helper autiste et des tutos qui commencent par "Comment insérer un copyright dans votre programme" (véridique : cherchez sur le web !) et enchaîne sur "Créer un menu dans une fenêtre", ça fait beaucoup. Sans rire, ce genre de truc est extrêmement dangereux pour le PC d'un gars comme moi... Dix minutes de plus et je transperçais l'écran à coup de tête. Dangereux je vous dis !
  • C après C++, connaissant le Fortran ? Mouais...
  • Ada serait sans doute le plus intéressant, mais il y a peu de chance qu'il me serve en milieu professionnel, vu qu'il est le plus souvent dédié au systèmes embarqués (domaine intéressant, mais un peu loin de ma branche).

L'utilisation éventuelle d'un langage en entreprise m'aide donc peu.

Concept ?
Aqui lo paradigme !

Il reste les "concepts".
Cela fait déjà un bon moment que le monde de la programmation fonctionnelle me fascine : attraction/répulsion.
Attraction car c'est une grande famille de langages, de LISP à Haskell en passant par Scheme et OCaml avec des méthodes intéressantes.
Répulsion car jusqu'ici, j'ai toujours été incapable de "décrypter" le moindre bout de code fonctionnel aperçu ici ou là : crispant.
Il y a aussi d'autres "concepts" (paradigmes en l'occurrence ici) : logique (PROLOG), concurrent (Ada, encore !), par contrainte...

Finalement...
Tout ça pour ça...

Finalement, c'est par hasard que je me suis mis... au Scheme.
Un article, chez RubyInside, décrivait un interpréteur pour Scheme, codé en Ruby, dans le bus. J'ai voulu tester. Du coup, il m'a fallu taper un peu de Scheme ; du coup, j'ai lu du Scheme ; du coup je me suis mis à comprendre un peu le Scheme ; du coup, j'apprends le Scheme.
Pour être tout à fait franc, ce langage faisait déjà parti de ceux qui me tentaient fortement, avec le LISP, l'OCaml, Io et Cobol (non, pour le Cobol, j'd3conne !).
Io a perdu car je voulais voir autre chose que de l'OO. Quite à se lancer dans le fonctionnel, autant prendre un langage "simple" : l'OCaml me semblait "trop riche" car multi-paradigme. Enfin, le LISP a eu un petit désavantage : cette citation de G. Chaitin sur la "pureté" d'un langage.
Scheme donc, avec l'interpréteur MzScheme (Bus-Scheme, celui en Ruby étant... peu utilisable ?).

Effectivement, Scheme est austère. Mais il semble reconnu pour son côté pédagogique et est (hormis pour les parenthèses) assez bref dans sa syntaxe : il y a une certaine élégance proche des maths je trouve. Il est vieux, mais a un certain charme... et j'avoue que je l'apprends avec un certain plaisir. Et pour ma bonne conscience professionnelle, Scheme est utilisé dans certains codes de calculs industriel, en appoint (bientôt un article sur "Quel(s) langage(s) dans tel programme ?").Que demander de plus ?

Références et Docs :

D'abord, deux textes pleins de sagesse (si si, il y a un rapport avec le reste...) :
L'article sur Bus-Scheme, l'implémentation en Ruby :
Commençons gentiment en Scheme (avec un interpréteur qui marche !) :
Pour tout le reste vu dans cet article, Wikipédia saura répondre... sinon demandez toujours !



lundi 7 janvier 2008

Formats en Fortran

En Fortran 90, la gestion des entrées-sorties est assez spartiate. Il est possible d'utiliser le format libre pour écrire ou lire ses données, mais l'emploi des formats est vivement recommandé si l'on veut être précis avec ses valeurs numériques (pour les flottants notamment) ou si l'on souhaite printer des choses d'une manière "fixe" (pas de décalage de colonne pour un tableau, par exemple). Le code ci-dessous illustre la plupart des descripteurs de format disponibles en Fortran (hormis les caractères de contrôle d'impression pour imprimante : "+", "0", "1", ... --> pour votre santé mentale, n'imprimez pas de Fortran !).

Note :

J'ai toujours codé en Fortran 90. Le code et les commentaires suivants sont donc au moins valables pour cette version et les suivantes (95 et 2003). Cependant, je ne peux pas assurer leur validité pour les versions antérieures de Fortran (77 et avant).

Code :



! Gestion des formats en fortran
PROGRAM main
INTEGER :: entier
REAL*8 :: flott
CHARACTER(LEN = 8) :: chaine
LOGICAL :: vamosalaplaya

entier = 4568
flott = 56.456
chaine = "truites"

vamosalaplaya = .TRUE.

! Sans format
PRINT*, "-----Sans format-----"
PRINT*, entier
PRINT*, flott
PRINT*, chaine
PRINT*, vamosalaplaya

! Avec formats
PRINT*, "-----Avec formats-----"
PRINT '(I6)', entier
PRINT '(F6.3)', flott
PRINT '(A7)', chaine
PRINT '(L3)', vamosalaplaya

! Combinaisons
PRINT*, "-----Combinaisons-----"
PRINT '(I4,3X,F5.2)', entier, flott
PRINT '(2(I4,1X,F5.2,2X))', &
entier,flott,&
2*entier,flott-1.5
PRINT '("N = ",I4,/,"x = ",F6.3)',&
entier, flott
PRINT '(T20,I4,T1,A7)',entier, chaine

! Notation exponentielle
PRINT*, "-----Exponentielle-----"
PRINT '(E8.2)', flott
PRINT '(E9.3)', flott
PRINT '(E10.4)', flott

! Erreurs
PRINT*, "-----Erreurs-----"
PRINT '(I3)', entier
!PRINT '(I4)', flott
! --> erreur a l'exe
PRINT '(E6.2)', flott
PRINT '(I4,1X,T3,F6.3)', entier, flott

END PROGRAM main


Résultats :

 -----Sans format-----
4568
56.4560012817383
truites
T
-----Avec formats-----
4568
56.456
truites
T
-----Combinaisons-----
4568 56.46
4568 56.46 9136 54.96
N = 4568
x = 56.456
truites 4568
-----Exponentielle-----
0.56E+02
0.565E+02
0.5646E+02
-----Erreurs-----
***
******
4556.456


Descripteurs :

Un format en fortran se présente entre quotes et parenthèses. Il est utilisable en écriture (comme ici avec PRINT, ou avec WRITE dans un fichier), et en lecture (READ). On utilise "*" pour indiquer un format libre (pas de format en fait !). Attention, il est nécessaire d'utiliser le même format en lecture que celui employé en écriture lors de la relecture de données (sans quoi les castors mutants prendront le contrôle de nos cerveaux). Passons en revue les descripteurs utilisés :
  • Entiers : Iw, avec w le nombre d'emplacements.
  • Réels, notation flottante : Fw.d avec w emplacements et d chiffres décimaux.
  • Réels, notation exponentielle : Ew.d avec w emplacements (penser au "E+" !) et d décimaux pour la mantisse (pas l'exposant, l'autre...).
  • Booléens : Lw avec w emplacements (intérêt d'écrire des booléens ?).
  • Chaîne : Aw
  • Espaces : wX pour w espaces (à noter que le w se met ici avant).
  • Changement de ligne : / ('(/,/)' pour un saut de ligne donc).
  • Facteur de répétition : exemple : '(2(I4,1X))' équivaut à '(I4,1X,I4,1X)'
  • Positionneur de tampon : Tw, avec w la position absolue dans la chaîne.
  • Libellés : entre double-quotes.

Commentaires :

Oui, c'est lourd. Oui, c'est une source intarissable d'erreurs. En particulier le coup du déplacement de tampon (à éviter à mon avis), les flottants et le facteur de répétition en cas d'inattention... Le A pour les chaînes ne prend pas obligatoirement d'argument (w dans notre notation). A noter qu'il est souvent conseillé de laisser le premier caractère d'impression libre (un espace, quoi) pour éviter tout soucis avec une sortie moyennement standard (avec caractère de contrôle notamment : vous noterez que c'est le comportement par défaut en format libre pour les chaînes de caractères).

En cas d'erreur de ma part ou autre, n'hésitez pas à poster.

vendredi 4 janvier 2008

RubyShyne v0.6

Allez hop, une petite mise à jour de RubyShyne qui commence à marcher pas trop mal...
  • Ajout du Java et Groovy pour les langages
  • Corrections de quelques petites erreurs
  • Léger nettoyage
Pour rappel, il génère du HTML avec balises "pre" mais est facilement modifiable pour prendre "text-area" (peu pratique chez Blogger), et je l'utilise depuis quelques temps maintenant pour présenter mes bouts de codes sur ce blog (tag "code" pour voir des exemples).

Encore une fois, si vous utilisez cette modeste application, n'hésitez pas à me le faire savoir pour que je puisse l'améliorer.

RubyShyne v0.6 :

mercredi 2 janvier 2008

Variables métasyntaxiques

Pour démarrer l'année en beauté, un petit article ultra-technique sur un point essentiel de la programmation informatique : les variables métasyntaxiques.





Variables Métasyntaxiques ???

Il s'agit en fait très bêtement des noms "classiques" que l'on donne aux variables et fonctions pour des exemples de code ! En français, le plus connu étant toto (immanquablement suivi de titi, tata et tutu et parfois tonton). Je me suis toujours demandé pourquoi, mais il fallait bien choisir quelque chose... Le dernière réponse d'un éminent informaticien que j'ai obtenue ressemblait à "Pourquoi toto ? Pourquoi pas ! Mais si ça peut te faire plaisir, on va mettre titi !".

En anglais : foo


L'article de Wikipedia à ce sujet nous apprend également l'origine des équivalents anglophones de toto : foo (que je croyais vouloir dire "Fully Object Oriented"...), bar et baz. foo signifie en fait fucked up, et foobar, parce que fucked up beyond all repair ! Marrant...
Au passage, l'article anglais de Wikipedia à ce sujet est assez bavard sur les nombres les plus souvent utilisés en exemple... Du 42, réponse à la question "Le sens de la vie, l'univers et tout le reste", au 12648430 (COFFEE en hexadécimal...).

Variables implicites en Fortran :

Par ailleurs, l'article francophone de Wikipedia parle d'une petite particularité à connaître en Fortran : les variables implicites. En effet, par défaut, le Fortran accepte l'utilisation de variables sans déclaration de leur type : celles-ci seront typées automatiquement à peu près comme suit :
  • De i à n : INTEGER
  • x, y, z : REAL
  • Les autres : no sé ! (et peut dépendre éventuellement du compilo dans mon souvenir...)
Alors que les choses soient claires, même si ça peut paraître bien utile, en particulier pour les itérateurs (i, j, k...) ou les variables de fonctions (x, y, z), c'est TRÈS MAL ! Et ça explique pourquoi un code "propre" en Fortran comporte quasiment toujours la ligne "IMPLICIT NONE" vers le début (mais après les includes, dont la cible est d'une certaine manière implicite pour le compilateur...).

Et voilà. Rien de prodigieux, mais commencer l'année en étant un peu moins bête (mais un peu alors !), c'est déjà pas si mal !

samedi 22 décembre 2007

RubyShyne

RubyShyne

est un outil de bureau, implémenté en Ruby, convertissant un code source en HTML coloré syntaxiquement (pour le présenter sur une page web, par exemple). Ce petit code est placé sous la licence libre BSD. Il supporte actuellement les langages Ruby, Java, Fortran et Groovy, et est facilement paramètrable pour obtenir le style de votre choix.

is a desktop-tool implemented in Ruby. It converts source code into HTML with syntax highlightment (in order to paste it on a web page, for instance). This humble code is under free-software BSD licence. Its current version supports Ruby, Java, Fortran and Groovy programming languages. You can easily configure it to get the highlighting style of your choice.

Exemple / Example :


=begin
Let's test
RubyShyne
and Duck Typing
!
=end

class Duck
attr_reader :name, :position

def initialize who
@name = who
@position = 0.0
@@legs = 2
end

def walk miles
@position += miles
end

def quack
puts "KWAAAAK !!!"
end
end

# Let's call one Herbert
a_duck = Duck.new "Herbert"

$weather = "Sunny"

for i in (0..2)
a_duck.quack
end

# Where are you going bro ?
a_duck.walk 10.0
puts "Herbert walked ", a_duck.position.to_s,\
"miles."


ATTENTION : un interpréteur Ruby est nécessaire à son utilisation !

WARNING: a Ruby interpreter is necessary to use it !

4/01/2008 : v0.6 - comment

Documentation et manuel (fichier lisez_moi.txt) sont inclus dans l'archive.

Doc and user manual (readme.txt file) are included into the archive.

N'hésitez pas à me contacter pour toute question, rapport de bug ou suggestion.
Feel free to contact me for any question, bug report or suggestion.


Mise à jour / Update : 4/01/2008

samedi 15 décembre 2007

Fortran : Coloration de graphe

Aujourd'hui, un peu de théorie des graphes en Fortran 90 ! (Je teste la coloration avec Rubyshyne en Fortran...)

Il s'agit d'un programme de coloration de graphe. Celle-ci est utilisée dans divers domaine, par exemple pour colorer automatiquement une carte avec différentes entités (pays, régions ou autre).

Comment ?

En consultant Wikipedia, je me suis rendu compte que j'ai "refait" sans le savoir l'algorithme classique pour ce problème, à savoir l'algo de Welsh & Powell. Pour la petite info, cet algo se base en partie sur le théorème des 4 couleurs, premier théorème mathématique dont la démonstration a nécessité l'utilisation d'un ordinateur (près d'un siècle après sa première formulation !).

Entrées-Sorties :

Ce programme prend en entrée la matrice du graphe à analyser, précédée du nombre de sommets (fichier tab.dat). Exemple :

6
0 1 1 0 0 0
1 0 1 0 1 0
1 1 0 1 1 0
0 0 1 0 0 1
0 1 1 0 0 0
0 0 0 1 0 0

Ce qui donne en graphe et en "carte" (déjà colorés ici pour l'exemple) :









Le code :


PROGRAM Coloration
IMPLICIT NONE
integer, allocatable :: A(:,:)
integer, allocatable :: Degree(:), AliasD(:), B(:), Color(:)
integer :: i, n, tmp, tmpD, ii, icolor
character(len=999) :: format_tab
character(len=6) :: motif = 'I1,1X,'
logical :: pas_adj

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! LECTURE DU GRAPHE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
PRINT*, ' '
OPEN(UNIT=10, FILE='tab.dat', FORM='formatted', STATUS='OLD')

READ(10,'(I6)') n
PRINT*, 'Taille du graphe : ', n
Print*, ' '
ALLOCATE(A(n,n))
ALLOCATE(Degree(n))
ALLOCATE(AliasD(n))
ALLOCATE(B(n))
ALLOCATE(Color(n))

Color = 0

format_tab = '('
DO i = 1, n-1
format_tab = format_tab(1:(6*i-5))//motif
END DO

format_tab = format_tab(1:(6*n-5))//'I1)'

PRINT*, 'Matrice du graphe : '
DO i = 1, n
READ(10, format_tab) A(i, 1:n)
B(i) = i
PRINT*, A(i, 1:n)
END DO
PRINT*, ' '

CLOSE(10)

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

! TRI PAR DEGRE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
DO i = 1, n
Degree(i) = SUM(A(i,1:n))
END DO

AliasD = Degree

ii = 1
DO WHILE (ii < n)
IF (AliasD(ii+1)>AliasD(ii)) THEN

tmp = B(ii)
tmpD = AliasD(ii)
B(ii) = B(ii+1)
AliasD(ii) = AliasD(ii+1)
B(ii+1) = tmp
AliasD(ii+1) = tmpD
IF (ii > 1) THEN
ii = ii - 1
ELSE
ii = 1
END IF
ELSE

ii = ii + 1
END IF
END DO

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! COLORATION
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Color(B(1)) = 1
DO icolor = 1, 4
ii = 2
DO WHILE (ii < n+1)
IF (Color(B(ii))==0) THEN


pas_adj = .TRUE.
DO i = 1, n
IF ((Color(i)==icolor).AND.(A(B(ii),i)/=0)) THEN
pas_adj = .FALSE.

END IF
END DO

IF (pas_adj) THEN
Color(B(ii)) = icolor
END IF


END IF
ii = ii + 1
END DO
END DO

!!!!!!!!!!!!!!!!!!!!!!!!!!

! RESULTATS
!!!!!!!!!!!!!!!!!!!!!!!!!!
PRINT*, ' '
PRINT*, 'Coloration : '
PRINT*, Color

END PROGRAM Coloration

mardi 11 décembre 2007

50 ans du Fortran

Le Fortran, langage informatique pionnier, fête cette année son 50ème anniversaire. Rappelons qu'il est né, après une grossesse de 3 ans environ, dans les laboratoires d'IBM. Malgré l'aspect assez repoussant que nous lui connaissons aujourd'hui, c'était un (très) beau bébé, et John Backus n'a pas hésité à le reconnaître comme étant son enfant, et à l'appeler Fortran, pour FORmula TRANslating system (comme son oncle, donc).

Deux articles sur l'évènement :

Since then it has evolved through many versions, each more powerful than the last, and even now Fortran is still the language of choice in many areas of physics.
Finally, there is no need to be a religious extremist; these days, procedures in different languages can be intermixed (which will only become easier). Different subsets of applications can be written in the most appropriate language, e.g. Java for the web, and all can be glued together in a PYTHON framework.


Un "NPC" ("NON-Personal Computer !") dans les années 50.

Une petite pensée pour John Backus, le papa de la bête, qui nous a quitté en Mars dernier. Il est également le géniteur, avec Peter Naur, de la notation BNF (Backus-Naur Form), décrivant la syntaxe de langages de programmation de niveau supérieur à l'Assembleur.
Bon anniversaire Fortran !