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

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Haskell Discussion :

Index too large incomprehensible


Sujet :

Haskell

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut Index too large incomprehensible
    Bonjour,
    Malgré toutes les gardes que j'ai mis pour limiter la valeur de l'indice à 15 pour le choix de la couleur, j'ai le message
    <interactive>: Prelude.(!!): index too large

    Voici le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    import Data.Monoid
    import System.IO
    import System.Random
    import Graphics.Gloss
     
    main = do
            affiche 
     
    affiche = display  
    	 (InWindow
    	       "Pascal"
    		(300, 300)
    		(10, 10))
             black
             (picture)
     
    picture = pictures (listOfpoints n a i j b coul)  -- ligne 17
        where
    	a = [1,1,1,2]
    	n = 182400
            i = 1
    	j = 1
    	b = 0
    	coul = 0
     
    listOfpoints 0 _ _ _ _ _ = []
    listOfpoints n a i j b coul = point : listOfpoints (n-1) a' i' j' b' coul'
        where
    	i' = calci i j
    	j' = calcj i i' j
    	b' = calcb a n i' j'
    	a' = a ++ [b']
    	coul' = teinte b'
            point = dessin n i' j' coul'
     
    calci i j
    	|j == i = i + 1
    	|otherwise = i
     
    calcj i i' j 
    	|i' > i= 0
    	|j == i' = j
    	|otherwise = j + 1
     
    calcb a n i' j'
    	|j' == 0 = 1
    	|j' == i' = (a  !! (n + 4 + j')) 	
    	|otherwise = (a !! (n + 4 + j')) + (a !! (n + 4 + j' - i' ))`mod`2
     
    teinte b'
    	|b' == 0 = 0
    	|b' < 128 = ((256`mod`(256 - 2*b'))`mod`13)
    	|otherwise = 0
     
    dessin n i' j' coul' = pictures
     
          [ (translate (fromIntegral i') (fromIntegral j') (color (myColor (coul')) (circle 1.0)))
          , (translate (- (fromIntegral i')) (fromIntegral j') (color (myColor (coul')) (circle 1.0)))
          ,	(translate (fromIntegral i') (- (fromIntegral j')) (color (myColor (coul')) (circle 1.0)))
          ,	(translate (- (fromIntegral i')) (- (fromIntegral j')) (color (myColor (coul')) (circle 1.0)))
          ,	(translate (fromIntegral j') (fromIntegral i') (color (myColor (coul')) (circle 1.0)))
          ,	(translate (- (fromIntegral j')) (fromIntegral i') (color (myColor (coul')) (circle 1.0)))
          ,	(translate (fromIntegral j') (- (fromIntegral i')) (color (myColor (coul')) (circle 1.0)))
          ,	(translate (- (fromIntegral j')) (- (fromIntegral i')) (color (myColor (coul')) (circle 1.0)))
          ]
     
    myColor coul'
    	|coul' < 0 = 0	
    	|coul' < 16 = ([ca,cb,cc,cd,ce,cf,cg,ch,ci,cj,ck,cl,cm,cn,co,cp] !! coul')
    	|otherwise = 0
     
    ca = white
    cb = light(light yellow)
    cc = light yellow
    cd = yellow   
    ce = light(light orange)
    cf = light orange
    cg = orange
    ch = light (dark orange)
    ci = light red
    cj = red
    ck = dark red 
    cl = light violet
    cm = violet
    cn = light(light (dark violet))
    co = light ( dark violet)
    cp = blue
    Le problème est la valeur b', car si j'élimine b' du calcul de coul' tout marche.
    par exemple pour coul' = n`mod`13 le dessin est bon (bien sur ce n'est pas Pascal) :
    Nom : PascalFaux.jpg
Affichages : 187
Taille : 257,2 Ko
    Ou encore pour coul' = teinte ((i'*j')`div`13) avec otherwise = 13
    Nom : PascalFaux1.jpg
Affichages : 183
Taille : 92,0 Ko
    Je ne trouve pas où est le problème.
    Pourriez- vous m'aider svp ?

  2. #2
    Membre averti
    Avatar de Chatanga
    Profil pro
    Inscrit en
    décembre 2005
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : décembre 2005
    Messages : 211
    Points : 338
    Points
    338
    Par défaut
    Pour commencer, voici un fragment de code que j’utilise fréquemment pour chasser le bug :
    Code Haskell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    import Data.List
    import qualified Debug.Trace as Trace
     
    trace :: Show a => String -> a -> a
    trace t a = Trace.trace (t ++ " = " ++ show a) a
    -- trace _ = id
     
    traceList :: Show a => String -> [a] -> [a]
    traceList t as = Trace.trace (t ++ " = [\n\t" ++ intercalate "\n\t" (map show as) ++ "\n]") as
    --traceList _ = id

    Ajoutons-le en tête de ton programme et modifions légèrement le bout de code qui suit :
    Code Haskell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    calcb a n i' j'
        |j' == 0 = 1
        |j' == i' = (a  `getAt` (n + 4 + j')) 	
        |otherwise = (a `getAt` (n + 4 + j')) + (a !! (n + 4 + j' - i' ))`mod`2
     
    getAt :: Show a => [a] -> Int -> a
    getAt t i = (traceList "array" t) !! (trace "index" i)

    Compilons, exécutons et constatons :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    index = 182404
    array = [
    	1
    	1
    	1
    	2
    	1
    ]
    CodinGame: Prelude.(!!): index too large
    Ce n’est donc visiblement pas déconnant de la part de Haskell de crier au loup. Quant aux inutiles gardes plus bas... bah ils ne gardaient visiblement pas la bonne porte .

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Merci pour ta réponse et le code qui me sera très utile.
    Si j'ai bien compris l'indice trop long concerne la liste a.
    Le piège est que le b' étant toujours calculé ça marchait sauf en utilisant b' dans calc', alors qu'apparemment l'erreur se produit dans le calcul du b'. Pour un debutant en Haskell c'est difficile de saisir. Pour comprendre j'ai modifié mon code selon ton exemple et aucune erreur n'est signalée si je ne calcule pas calc' à partir du b' (mon deuxième exemple). Il est vrai que la liste n'est pas utilisée ailleurs que dans le calcul du b', mais le b' est calculé et ajouté à la liste, ou je me trompe? Les i' et j' qui font partie de l'indice donnent des parfaites images, n est immuable, il ne reste que le décalage de départ de la liste = 4 et le décalage i. La liste représente un tableau i,j mais elle est constituée uniquement des éléments i = 2 à 150 et j = 1 à i. Je vais revoir mes calculs.

  4. #4
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : avril 2003
    Messages : 6 245
    Points : 8 560
    Points
    8 560
    Par défaut
    Tu sembles avoir beaucoup de problèmes d'indices. Ceci est généralement révélateur d'un problème de design. Les problèmes d'indices sont communs en programmation impérative à cause des itérations, et ton programme est fondamentalement bâti sur une itération, même si elle est implémentée par une récursion. De plus tu entremêles la génération du triangle de Pascal et sa transformation en image.

    Haskell a une réputation de langage où "si ça compile, ça marche"... Ce n'est évidemment pas le cas pour toi mais c'est parce que tu n'utilises pas du tout les points fort de Haskell : par exemple Haskell, grâce à son évaluation paresseuse, est l'un des rares langages où l'on peut pratiquement toujours séparer la génération et la consommation d'une structure de donnée.

    Partant de cette idée et supposant que tu souhaites achever un triangle de Pascal où la couleur de chaque case correspond au module de la valeur, commençons par générer le triangle de Pascal :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    pascal :: [[Int]]
    pascal = iterate genRow [1]
      where
        genRow xs = 1 : go xs
        go [x] = [1]
        go (x:y:xs) = x+y : go (y:xs)
    (Integer au lieu de Int si tu veux des images vraiment grandes, au delà de 1000 lignes, même un Int sur 64 bits devient insuffisant... Ou tu pourrais faire ton mod plus tôt)

    Ensuite voyons comment le parcourir en étant conscient des coordonnées de façon efficace et sans risque d'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    mapIx2d :: (Int -> Int -> a -> b) -> [[a]] -> [[b]] 
    mapIx2d f = zipWith (\row -> zipWith (f row) [0..]) [0..]
    Ne nous reste plus qu'à générer l'image :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    picture :: Picture
    picture = pictures . concat . mapIx2d point $ take 300 pascal
      where
        point n k p = translate (fromIntegral k) (fromIntegral n) . color (chooseColor p) $ circle 1
    Ou quelque chose comme ça...

    Il n'y a pratiquement aucun risque d'erreur dans cette procédure, en particulier aucun dépassement d'indice n'est possible, et pratiquement toute étourderie lourde sera détectée par un problème dans les types. Il est également possible de tester chacune des pièces séparément et aisément avec GHCi. Évidemment le résultat graphique n'est pas garanti mais comme l'algorithme lui-même fonctionne et est minimal et séparé du rendu graphique lui-même, les ajustements peuvent être faits avec une certaine confiance que le programme continuera à fonctionner.

    --
    Jedaï

  5. #5
    Expert éminent
    Avatar de Jedai
    Homme Profil pro
    Enseignant
    Inscrit en
    avril 2003
    Messages
    6 245
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : avril 2003
    Messages : 6 245
    Points : 8 560
    Points
    8 560
    Par défaut
    Citation Envoyé par vasilpapa Voir le message
    Merci pour ta réponse et le code qui me sera très utile.
    Si j'ai bien compris l'indice trop long concerne la liste a.
    Le piège est que le b' étant toujours calculé ça marchait sauf en utilisant b' dans calc', alors qu'apparemment l'erreur se produit dans le calcul du b'. Pour un debutant en Haskell c'est difficile de saisir.
    Le problème n'a vraiment rien à voir avec Haskell, c'est simplement qu'au premier appel de listOfpoints, n vaut 182400, a' est une liste de 4 éléments et tu demandes l'élément à l'indice "n + 4 + j'" où j' est positif...
    A moins que tu veuilles dire que si tu laisses la ligne définissant b' mais que tu cesses de l'utiliser par ailleurs l'erreur disparaît ? Dans ce cas, c'est effectivement le fait qu'Haskell est paresseux qui fait que b' n'étant pas utilisé, il ne sera jamais calculé et donc l'erreur d'indice ne sera pas rencontrée, ceci est en fait assez utile, par exemple tu peux définir certaines variables dans un where qui ne sont pas toujours bien définies (division par zéro, ...) mais tant qu'elle ne sont utilisées que dans des cas où elle font sens, le programme tournera sans erreur.

    --
    Jedaï

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    mai 2006
    Messages
    113
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : mai 2006
    Messages : 113
    Points : 64
    Points
    64
    Par défaut
    Merci, j'ai compris.
    Je signale seulement que la liste ne comporte pas le triangle de Pascal, mais les valeurs calculée dans b', mon algorithme étant erroné. Une fois corrigé voici un des résultats :
    Nom : Pascal 15-8.jpg
Affichages : 169
Taille : 226,4 Ko

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. SQL LOADER : value too large ...
    Par magic charly dans le forum SQL*Loader
    Réponses: 29
    Dernier message: 25/10/2007, 18h16
  2. Code too large for try statement
    Par ze veritable farf dans le forum Servlets/JSP
    Réponses: 3
    Dernier message: 13/06/2006, 20h41
  3. Réponses: 1
    Dernier message: 22/07/2005, 13h32
  4. Error 124 : statement part too large
    Par cedchantrel dans le forum Turbo Pascal
    Réponses: 4
    Dernier message: 29/03/2005, 10h30
  5. pb pour créer des index [too many keys]
    Par Issam dans le forum Débuter
    Réponses: 3
    Dernier message: 19/01/2005, 20h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo