Avatar billede encorez Juniormester
13. februar 2018 - 11:11 Der er 13 kommentarer og
1 løsning

Kombinere typer med forskellige antal værdier

Min udfordring er ikke JAVA afhængig, men det er Java jeg programmerer i.

Jeg har flere typer med forskellige antal værdier:
F.eks.
Type: Bil; værdier: 1,2,3,4
Type: Tog; Værdier: 5,6
Type: Cykel; Værdier: 5,6,97
Type: Fly; Værdier: 10

Udfordringen er at lave en funktionen som kan lave alle mulige kombinationer af værdierne, for 2 typer af gangen.
F.eks. at kombinere Bil og Fly vil give:
B1,F10
B1, B2, F10
B1, B2, B3, F10
B1, B2, B3, B4, F10
B2, F10
B2, B3, F10
B2, B3, B4, F10
B3, F10
osv

Nogle gode ideer?
Avatar billede Slettet bruger
13. februar 2018 - 13:32 #1
du kunne jo lave det så elegant, at biler er negative heltal, og fly positive ?
Avatar billede encorez Juniormester
13. februar 2018 - 15:14 #2
Men selv om jeg gør det, hvordan får jeg så lavet en funktion der gennemgår alle mulige kombinationer mellem alle værdierne i de to typer?
Avatar billede arne_v Ekspert
13. februar 2018 - 16:50 #3
Er antallet af typer fast?

Ja => 4 for loekker indeni hinanden

Nej => du skal bruge en rekursiv metode
Avatar billede encorez Juniormester
13. februar 2018 - 17:24 #4
Antallet af typer er fast ja, blot omkring 12-14. Men her skal jeg jo kun kombinere 2 af gangen.
Antallet af værdier er forskelligt fra type til type. For nogle typer er der 3 værdier, for andre 6, og for andre igen er der 12 værdier.
Avatar billede arne_v Ekspert
14. februar 2018 - 05:27 #5
Ah.

Saa noget a la:


import java.util.ArrayList;
import java.util.List;

public class Combi {
    public static class Type  {
        private String prefix;
        private int[] nos;
        public Type(String prefix, int... nos) {
            this.prefix = prefix;
            this.nos = nos;
        }
        public int length() {
            return nos.length;
        }
        public String getElement(int ix) {
            return prefix + nos[ix];
        }
        public List<String> getAllElements() {
            List<String> res = new ArrayList<String>();
            for(int i = 0; i < length(); i++) {
                res.add(getElement(i));
            }
            return res;
        }
    }
    private static void expand(List<String> base, List<String> a, int ix, List<List<String>> res ) {
        for(int i = ix; i < a.size(); i++) {
            List<String> newbase = new ArrayList<String>(base);
            newbase.add(a.get(i));
            res.add(newbase);
            expand(newbase, a, i + 1, res);
        }
    }
    private static List<List<String>> expand(Type typ) {
        List<List<String>> res = new ArrayList<List<String>>();
        List<String> a = typ.getAllElements();
        expand(new ArrayList<String>(), a, 0, res);
        return res;
    }
    private static String join(List<String> a1, List<String> a2) {
        StringBuilder sb = new StringBuilder();
        for(String s1 : a1) {
            sb.append("," + s1);
        }
        for(String s2 : a2) {
            sb.append("," + s2);
        }
        return sb.toString().substring(1);
    }
    public static void combine(Type typ1, Type typ2) {
        for(List<String> a1 : expand(typ1)) {
            for(List<String> a2 : expand(typ2)) {
                System.out.println(join(a1, a2));
            }
        }
    }
    public static void main(String[] args) {
        combine(new Type("B", 1, 2, 3, 4), new Type("F", 10));
    }
}
Avatar billede encorez Juniormester
20. februar 2018 - 21:14 #6
Hold da ferie, den virker perfekt :) Tusind tak.
Avatar billede encorez Juniormester
23. februar 2018 - 12:20 #7
Tillægsspørgmål, funktioner kombinerer værdier perfekt som de skal, men jeg sidder og nørder med at "fange" de værdi-kombinationer så jeg får dem returneret så jeg i en løkke kan arbejde med dem, kombination for kombination.

Kan funktionen "public static void combine(Type typ1, Type typ2) " returnere resultatet i et array eller lign?
Avatar billede arne_v Ekspert
23. februar 2018 - 14:57 #8
Det er nemt at generalisere.


import java.util.ArrayList;
import java.util.List;

public class Combi {
    @FunctionalInterface
    public static interface Handler {
        public void process(List<String> a1, List<String> a2);
    }
    public static class Type  {
        private String prefix;
        private int[] nos;
        public Type(String prefix, int... nos) {
            this.prefix = prefix;
            this.nos = nos;
        }
        public int length() {
            return nos.length;
        }
        public String getElement(int ix) {
            return prefix + nos[ix];
        }
        public List<String> getAllElements() {
            List<String> res = new ArrayList<String>();
            for(int i = 0; i < length(); i++) {
                res.add(getElement(i));
            }
            return res;
        }
    }
    private static void expand(List<String> base, List<String> a, int ix, List<List<String>> res ) {
        for(int i = ix; i < a.size(); i++) {
            List<String> newbase = new ArrayList<String>(base);
            newbase.add(a.get(i));
            res.add(newbase);
            expand(newbase, a, i + 1, res);
        }
    }
    private static List<List<String>> expand(Type typ) {
        List<List<String>> res = new ArrayList<List<String>>();
        List<String> a = typ.getAllElements();
        expand(new ArrayList<String>(), a, 0, res);
        return res;
    }
    public static void combine(Type typ1, Type typ2, Handler h) {
        for(List<String> a1 : expand(typ1)) {
            for(List<String> a2 : expand(typ2)) {
                h.process(a1, a2);
            }
        }
    }
}



import java.util.List;

import february.Combi.Type;

public class CombiDemo {
    private static String join(List<String> a1, List<String> a2) {
        StringBuilder sb = new StringBuilder();
        for(String s1 : a1) {
            sb.append("," + s1);
        }
        for(String s2 : a2) {
            sb.append("," + s2);
        }
        return sb.toString().substring(1);
    }
    private static void print(List<String> a1, List<String> a2) {
        System.out.println(join(a1, a2));
    }
    public static void main(String[] args) {
        Combi.combine(new Type("B", 1, 2, 3, 4), new Type("F", 10), CombiDemo::print);
    }
}
Avatar billede arne_v Ekspert
23. februar 2018 - 14:58 #9
Den printer naturligvis stadig.

Men du laver bar en:


private static void process(List<String> a1, List<String> a2) {
      // ...
}


der goer hvad du har brug for og sende den over som tredie argument.
Avatar billede arne_v Ekspert
23. februar 2018 - 15:05 #10
PS: Jeg har antaget at du er paa Java 8 eller nyere - det kan nemt omskrives til aeldre Java hvis noedvendigt.
Avatar billede encorez Juniormester
24. februar 2018 - 21:20 #11
Tusind tak :)
Jeg prøver at få de 2 classes til at virke og jeg får en fejl på "february" i linien "import february.Combi.Type;", kan du sige hvad der er galt der?
"february" er understreget og siger "cannot resolve symbol".

Jeg koder i IntelliJ IDEA og under "Project SDK" står der "1.8.0_131". Svarer det på om jeg bruger Java 8?
Avatar billede arne_v Ekspert
24. februar 2018 - 21:34 #12
Slet "february.". Jeg har klasserne i en package february, men jeg slettede den da jeg kopiered ind.
Avatar billede arne_v Ekspert
24. februar 2018 - 21:34 #13
Ja. Det er Java 1.8 alias Java 8 update (patch) level 131.
Avatar billede encorez Juniormester
24. februar 2018 - 21:43 #14
Ahhh, oki.

Jeg løste det ved at kopiere hele Combi-classen ind i CombiDemo.

Men jeg manglede stadig at få returneret resultatet til det sted hvor jeg kører "combine()", da det er der jeg skal bruges resultatet til at arbejde videre med.

Jeg lavede en
public static String kombistring = "";

Og denne
private static void print(List<String> a1, List<String> a2) {
        kombistring = kombistring + join(a1, a2)+";";
}

Og så efter min "combine" får jeg nu en variabel med resultatet som jeg kan arbejde videre med.
combine(new Type("B", 1, 2, 3, 4), new Type("F", 10), analyse_indicators2::print);
            System.out.println("kombistring:"+kombistring);


Tusind tak for hjælpen :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester