Récupérer informations d'un fichier

Résolu/Fermé
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 - Modifié le 21 mars 2021 à 00:09
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 - 23 mars 2021 à 19:06
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

charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 1
Modifié le 21 mars 2021 à 00:22
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...
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
21 mars 2021 à 09:06
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")));
    }
}
0
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 1
Modifié le 21 mars 2021 à 11:13
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 ?
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019
21 mars 2021 à 12:02
Avec tes deux tableaux tu vas avoir du mal à faire du tri en conservant la cohérence que weight[i] est associé à value[i]

Ok, tu n'as pas le droit d'utiliser les List, ça ne t'empêche pas quand même d'avoir une classe Item et un unique tableau, Item[] items, beaucoup plus simple à manipuler que deux tableaux en parallèle.

Il serait d'ailleurs bien plus logique d'avoir une méthode getRatio dans la classe Item pour faire ta division.

Quant au quicksort, là encore, à moins d'avoir des contraintes scolaires dessus, autant utiliser le tri de Java : Arrays.sort qui est bien meilleur que tout ce que tu pourras écrire à la main.

Arrays.sort(items, Comparator.comparing(Item::getRatio));
0
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 1 > KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024
Modifié le 21 mars 2021 à 19:06
PS: pourquoi ne pas utiliser une ArrayList<Item> plutôt qu'une List<Item>?

Pour les tableaux, on m'a dit d'en utiliser 2, un pour le poids, un pour la valeur (je redemanderai au cas où, cependant, c'est vrai que 2 tableaux c'est vraiment pas pratique).

Mais dans le cas où ce sont bien 2 tableaux qu'il faut manipuler, c'est pour cette raison que je pensais implémenter quicksort (ou un autre algo de tri), pour prendre en compte qu'il n'y a pas un, mais deux, et à trier en parallèle, et qu'ils sont liés par le ratio. Parce qu'on est d'accord que je ne peux pas utiliser de méthode déjà existante pour trier deux tableaux en même temps ?

Donc finalement, pour implémenter la classe Item sinon, je pourrais faire ceci ?
public class Item {

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

}

mais au final, j'ai l'impression que ça complexifie le code pour pas grand chose.
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019 > charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022
21 mars 2021 à 19:28
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.
0
KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024 3 019 > KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024
21 mars 2021 à 20:35
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.
0
charline159 Messages postés 208 Date d'inscription lundi 14 août 2017 Statut Membre Dernière intervention 22 juin 2022 1 > KX Messages postés 16753 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 25 novembre 2024
Modifié le 23 mars 2021 à 17:07
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 ?
0