Récupérer informations d'un fichier [Résolu]

Signaler
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
-
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
-
Bonjour, j'essaie actuellement de récupérer les informations du fichier suivant:
1000
124 13
156 14
138 13
143 14
231 25
214 20
98 10
178 16
205 19
189 17
163 16
112 12
201 16
302 29
222 23


- la première ligne est stockée dans
int capacity

- les infos de la colonne de gauche sont stockées dans
double[] weight

- les infos de la colonne de droite sont stockées dans
double[] value


J'arrive à quasiment tout récupérer, sauf le tout dernier chiffre, à la dernière ligne (23), qui n'apparait pas dans mon tableau value:
capacity = 15
weight = [124.0, 156.0, 138.0, 143.0, 231.0, 214.0, 98.0, 178.0, 205.0, 189.0, 163.0, 112.0, 201.0, 302.0, 222.0]
value = [13.0, 14.0, 13.0, 14.0, 25.0, 20.0, 10.0, 16.0, 19.0, 17.0, 16.0, 12.0, 16.0, 29.0, 0.0]


Pourriez-vous m'expliquer d'où vient l'erreur s'il vous plaît?

Voilà mon code:
package com.company;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;

public class Backpack {

    private int capacity;

    private double[] weight;
    private double[] value;


    /**
     * construtor of the backpack from the file
     */
    public Backpack(File file) throws FileNotFoundException {

        // note: scan data from file
        Scanner scan = new Scanner(file);
        String sentence = "";
        int nbOfElt = -1; //note: because first line doesn't count
        while (scan.hasNextLine()){
            sentence = sentence + scan.nextLine()+" ";
            nbOfElt++;
        }
        System.out.println(nbOfElt);

        // note: retrieval of capacity (first four char of the file)
        String capacityString = sentence.substring(0,4);
        this.capacity = Integer.parseInt(capacityString);


        // note: retrieval of weight and value in one String array
        sentence = sentence.substring(4);
        String[] weightAndValue = sentence.split("\\s");


        // note: weight = even index
        // note: value = odd index
        double[] specsD = new double[weightAndValue.length];
        int d = 0;
        for (int i = 0; i < weightAndValue.length; i++) {
            if (!weightAndValue[i].isEmpty()){
                Double data = Double.parseDouble(weightAndValue[i]);
                double dataD = (double) data;
                specsD[d] = dataD;
                d++;
            }

        }


        this.weight = new double[nbOfElt];
        int w = 0;
        this.value = new double[nbOfElt];
        int v = 0;

        for (int i = 0; i < specsD.length; i++) {

            if (i%2==0){ //note: even index = weight
                this.weight[w] = specsD[i];
                if (w==nbOfElt-1){ break; }
                w++;
            }
            if (i%2==1){ //note: odd index = value
                this.value[v] = specsD[i];
                v++;
            }
        }
        System.out.println(Arrays.toString(this.weight));
        System.out.println(Arrays.toString(this.value));

    }


    /**
     * accessors
     */
    public int getCapacity(){
        return this.capacity;
    }

    public double[] getWeight(){
        return this.weight;
    }

    public String printWeight(){
        return Arrays.toString(this.weight);
    }

    public double[] getValue(){
        return this.value;
    }

    public String printValue(){
        return Arrays.toString(this.value);
    }
    /**
     * end accessors
     */


    public double getRatio(int i){
        return this.value[i]/this.weight[i];
    }


    public void sortByRatio(){
        //fixme
    }



    /**
     * test
     */
    public static void main(String[] args) throws FileNotFoundException {


        File file0 = new File("C:\\Users\\...\\src\\com\\company\\sac0.txt");
        Backpack backpack0 = new Backpack(file0);

    }



}

3 réponses

Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
1
j'ai vainement tenté
for (int i = 0; i < specsD.length; i++) {

            if (i%2==0){ //note: even index = weight
                this.weight[w] = specsD[i];
                if (w<nbOfElt-1){ w++; }

            }
            if (i%2==1){ //note: odd index = value
                this.value[v] = specsD[i];
                if (v<nbOfElt-1){ v++;}
            }
        }


mais j'obtiens
15
[124.0, 156.0, 138.0, 143.0, 231.0, 214.0, 98.0, 178.0, 205.0, 189.0, 163.0, 112.0, 201.0, 302.0, 0.0]
[13.0, 14.0, 13.0, 14.0, 25.0, 20.0, 10.0, 16.0, 19.0, 17.0, 16.0, 12.0, 16.0, 29.0, 0.0]

ce qui est encore pire puisqu'il me manque les derniers index dans chaque tableau...
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021
2 817
Bonjour,

Ton problème est sur
if (w==nbOfElt-1){ break; }
parce que ça veut dire que tu arrêtes dès que le tableau weight est rempli, alors qu'il te reste encore à remplir une fois le tableau value.
Si tu faisais
if (v==nbOfElt-1){ break; }
dans le deuxième if, ça fonctionnerait.

Mais ouh là là, que c'est compliqué !

Tout d'abord, ta structure de données avec un double tableau, c'est maladroit, car la correspondance entre le poids et la valeur d'un élément repose sur leur position commune.
Java est un langage de programmation objet, il faut créer des classes pour représenter les différents objets que tu manipules. Tu as un sac avec des éléments dedans : donc il te faut une classe pour le sac et une classe pour les éléments que tu mets dedans.
De plus, les tableaux c'est bas niveau, en Java il faut privilégier les Collection (List, Set, Map)

Exemple :
class Item {
    double weight;
    double value;
}
class Backpack {
    int capacity;
    List<Item> items;
}


Quant à la lecture du fichier, ça peut se simplifier en utilisant correctement Scanner.
Au lieu de tout lire en String et de faire des conversions à tout va, tu peux directement lire les int et double qui composent le fichier et les ajouter directement à ton objet.

Exemple :
public Backpack(File file) throws FileNotFoundException {
    try (Scanner scan = new Scanner(file)) {
        capacity = scan.nextInt();
        items = new ArrayList<>();
        while (scan.hasNextDouble()) {
            double weight = scan.nextDouble();
            double value = scan.nextDouble();
            items.add(new Item(weight, value));
        }
    }
}


Le code complet pour tester :
package com.company;

public class Item {
    private final double weight;
    private final double value;
   
    public Item(double weight, double value) {
        this.weight = weight;
        this.value = value;
    }

    @Override
    public String toString(){
        return "Item [weight=" + weight + ", value=" + value + "]";
    }
}

package com.company;

import java.io.*;
import java.util.*;

public class Backpack {
    private int capacity;
    private List<Item> items;

    public Backpack(File file) throws FileNotFoundException {
        try (Scanner scan = new Scanner(file)) {
            capacity = scan.nextInt();
            items = new ArrayList<>();
            while (scan.hasNextDouble()) {
                double weight = scan.nextDouble();
                double value = scan.nextDouble();
                items.add(new Item(weight, value));
            }
        }
    }

    @Override
    public String toString(){
        return "Backpack [capacity=" + capacity + ", items=" + items + "]";
    }

    public static void main(String[] args) throws Exception {
        System.out.println(new Backpack(new File("E:/sac.txt")));
    }
}
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
1
Merci pour ta réponse.

Je suis d'accord avec toi sur les collections: d'ailleurs à la base, j'avais fait ça avec des ArrayList car c'est plus simple à manier justement, et d'ailleurs ça marchait parfaitement bien, mais on m'a dit que je devais utiliser des tableaux... donc j'ai recommencé avec des tableaux.

Pour le scan des double et des int, merci, je n'y avais pas pensé!

J'ai donc ceci finalement:
public Backpack(File file) throws IOException {

        Scanner scan = new Scanner(file);

        // note: size of arrays
        Path path = Paths.get(file.getPath());
        List<String> allLines = Files.readAllLines(path);
        int nbOfLines = -1; //note: -1 because first line doesn't count
        for (String line: allLines){ nbOfLines++; }
        out.println(nbOfLines);

        this.weight = new double[nbOfLines];
        this.value = new double[nbOfLines];



        // note: filling of arrays
        scan = new Scanner(file); //note: restart from the beginning
        this.capacity = scan.nextInt();

        int i = 0;
        while (scan.hasNextLine() && i<nbOfLines){
            double weight = scan.nextDouble();
            this.weight[i] = weight;

            double value = scan.nextDouble();
            this.value[i] = value;

            i++;
        }

    }


Par contre, maintenant, j'aimerais réorganiser les éléments de chaque tableau selon leur ratio valeur/poids croissant. Par exemple, avec:
[13.0, 14.0, 13.0, 14.0, 25.0, 20.0, 10.0, 16.0, 19.0, 17.0, 16.0, 12.0, 16.0, 29.0, 23.0]
[124.0, 156.0, 138.0, 143.0, 231.0, 214.0, 98.0, 178.0, 205.0, 189.0, 163.0, 112.0, 201.0, 302.0, 222.0]

Si (13.0/124.0) est le minimum du tableau, je ne fais rien puisque ces éléments sont déjà en début de tableau, sinon je les bouge.

Est-ce que quicksort serait une bonne idée pour trier ces deux tableaux ?
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021
2 817 >
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021

Si tu es obligé de garder les deux tableaux alors oublie la classe Item, tout en gardant en tête que ce n'est pas vraiment comme ça qu'il faudrait faire.

Après, le choix de l'algorithme de tri ne change rien, ils font tous la même chose : ils ordonnent une donnée là où tu vas devoir en ordonner deux, donc tu vas devoir faire du spécifique, ce qui est là encore contraire à la réutilisabilité caractéristique de la programmation objet.

Quant à l'utilisation de List plutôt que ArrayList c'est pour manipuler l'interface plutôt que l'implémentation, ce qui permet de manipuler plusieurs implémentation.
Par exemple Arrays.asList renvoie une List, mais ce n'est pas une ArrayList, donc si tu imposes d'utiliser une ArrayList, tu obliges à faire des conversions qui auraient pu être évitées si tu avais été moins restrictif.
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021
2 817 >
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021

Remarque : si on prends ce code : Structure générique pour les algorithmes de tris.

Tu peux trier ton Backpack comme ceci :
Backpack backpack = new Backpack(new File("E:/sac.txt"));
Sorter sorter = new MergeSorter(); // ou BubbleSorter, ou autre algorithme de tri
sorter.sort(backpack, 
        b -> b.weight.length, // Sizer
        (b, i) -> new double[] { b.weight[i], b.value[i] }, // Getter
        (b, i, v) -> {b.weight[i] = v[0]; b.value[i] = v[1]; }, // Setter
        (v1,v2) -> Double.compare(v1[0]/v1[1], v2[0]/v2[1])); // Comparator

Remarque : je suis passé ici par un double[2] intermédiaire qui contient juste {weight, value}, mais on pourrait aussi faire cela avec la classe Item.
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
1 >
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021

ok, je vois, en ce qui concerne List et ArrayList. Je penserais à faire ça la prochaine fois.

En effet, on nous a demandé de ne pas trop développer le côté "orienté objet" pour se concentrer pleinement sur l'algorithmique (mais je suis d'accord avec toi, c'est dommage, d'autant plus que mon niveau en POO n'est pas très élevé, donc ça serait l'occasion de pratiquer cet aspect-là justement...).

En tout cas, merci pour ton aide.

Par curiosité, quels sont les tris les plus demandés/utilisés en entreprise ?
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021
2 817 >
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021

En entreprise on ne s'amuse pas à faire des algorithmes de tri.
Java en a un, il fonctionne très bien, donc tout le monde l'utilise.
Pourquoi perdre du temps (et donc de l'argent) pour faire moins bien ?

Les détails de l'implémentation sont documentés ici : https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/util/List.html#sort(java.util.Comparator)
Messages postés
175
Date d'inscription
lundi 14 août 2017
Statut
Membre
Dernière intervention
8 avril 2021
1 >
Messages postés
16302
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
9 avril 2021

D'accord, tant mieux j'imagine. D'un autre côté, je me disais que connaître quelques tris pourraient aider à développer sa logique algorithmique...

Merci encore !