Klassen Algorithmus für das folgende Problem entwickeln?

Bitte aktiviere JavaScript!
Hallo zusammen,

ich stehe mal wieder vor ein Problem womit ich es nicht programmieren kann, oder zumindest nicht schön.

Im folgenden Bild habe ich 12 Kacheln, jede Kachelhat eine bestimmte Bezeichnung, das kommt vom chinesischen und steht jeweils für ein Tier. An sich fange ich bei Ty mit der Id und im Uhrzeigersinn wird immer um1 incrementiert. Weiter hat jede Kachel ein Monat mit sich.
12314
Ich will über ein Algorithmus eine bestimmte Kachel finden mit folgende Angaben:
1. Geburtsmonat
2. Geburtsuhrzeit, wobei hier nur die Stunden eine Rolle spielen.

Die Kacheln habe ich jeweils in ein Enum Chi mit den Monaten gespeichert wie folgt (hellgraue Wert steht für Monate):
12316

Beispiel: August hat den Kachel Dau.

Jetzt müsste ich noch die Geburtstuhrzeit einbeziehen und die Kacheln rückwärtslaufen

Beispiel August 14 Uhr, wenn ich auf die erste Abbildung schaue, bin ich bei Kachel Dau mit Monat August, 14 Uhr entspricht die untere Tabelle 7 Schritte zurücklaufen gegen Uhrzeigersinn, d.h. wir sind jetzt bei Mau.

Ergebnis: August 14 Uhr entsprich 1. Dau, 2. Mau

12317

Wie würdet ihr diesen Algo entwickeln?
Code:
public class Algo {

    public static void main(String[] args) {
        int birthmonth = 8;
        int birthtime = 14;
        
        for (Chi chi : Chi.values()) {
            if (chi.getValue()==birthmonth) {
                // an der Stelle ist es Dau               
            }
        }
    }
}
Ich hänge gerade bei dem zurücklaufen der Kacheln, was ist wenn das Zurücklaufen bis Ty (im Enum) geht, dann geht es mit Hoi, Tuat, Dau, etc. Ich denke Modulo ist an der Stelle richtig oder? Aber wie gehe ich da am Besten vor?
 

Anhänge

Spontan:

Dem enum eine statische Methode getForMonth(int month) geben, der kann dann entweder über iterieren oder über ne Map oder über den ordinal das passende für den Chi(?) zurückgeben. Zusätzlich ne Methode, die für gegebenes Chi(?) und Uhrzeit das passende zurückliefert, für das Berechnen ist %(*) dabei richtige, man muss nur negative Werte passend beachten, am einfachsten in dem man grundsätzlich vorher um 12 erhöht.



(* in Java btw Remainder und nicht Modulo, auch wenns hier keinen Unterschied macht)
 
Irgendwie erschließt sich mir dein Beispiel nicht. Wenn 14 Uhr NGO entspricht und das 7 Schritte gegen den Uhrzeigersinn von DAU bedeutete, dann komme ich auf DAN und nicht MAU?

Weiterhin ist mir nicht Kar, warum du dann nicht einfach die IDs entsprechend den Monaten vergibst. Wenn DAU dann 8 wäre, wäre DAN dann 8 - Uhrzeit / 2 = 1. Also wäre der erste einfach der mit der id = monat und der zweite = das Ergebnis der ersten Rechnung minus der Uhrzeit / 2.

Da fügt sich dann alles automatisch

Gruß

Claus
 
Spontan:

Dem enum eine statische Methode getForMonth(int month) geben, der kann dann entweder über iterieren oder über ne Map oder über den ordinal das passende für den Chi(?) zurückgeben. Zusätzlich ne Methode, die für gegebenes Chi(?) und Uhrzeit das passende zurückliefert, für das Berechnen ist %(*) dabei richtige, man muss nur negative Werte passend beachten, am einfachsten in dem man grundsätzlich vorher um 12 erhöht.



(* in Java btw Remainder und nicht Modulo, auch wenns hier keinen Unterschied macht)
Ist echt toll das du mein Problem verstanden hast, ich dachte schon das es zu kompliziert beschrieben ist.

Ich habe das mal so gemacht, aber irgendwas stört mich da noch, hast du da einen Vorschlag?

Code:
public class Algo {

    public static void main(String[] args) {
        Algo algo = new Algo();
        Chi chi1 = algo.findBy(8, 14);
        System.out.println(chi1);
        
        Chi chi2 = algo.findBy(8, 20);
        System.out.println(chi2);
    }

    private Chi findBy(int birthMonth, int birthTime){
        int steps =    getStepBacks(birthTime);
        if (steps > birthMonth) {
            steps = steps - birthMonth;
            steps = Chi.values().length-steps;
            return getChiByMonth(steps);
        }else {
            return getChiByMonth(birthMonth-steps);
        }
    }

    private Chi getChiByMonth(int month) {
        for (Chi chi : Chi.values()) {
            if (chi.getValue()==month) {
                return chi;
            }
        }
        return null;
    }
    
    private Integer getStepBacks(int birthtime) {
        if (0 < birthtime && birthtime <= 2)
            return 0;
        else if (2 < birthtime && birthtime <= 4)
            return 1;
        else if (4 < birthtime && birthtime <= 6)
            return 2;
        else if (6 < birthtime && birthtime <= 8)
            return 3;
        else if (8 < birthtime && birthtime <= 10)
            return 4;
        else if (10 < birthtime && birthtime <= 12)
            return 5;
        else if (12 < birthtime && birthtime <= 14)
            return 6;
        else if (14 < birthtime && birthtime <= 16)
            return 7;
        else if (16 < birthtime && birthtime <= 18)
            return 8;
        else if (18 < birthtime && birthtime <= 20)
            return 9;
        else if (20 < birthtime && birthtime <= 22)
            return 10;
        else if (22 < birthtime && birthtime <= 24)
            return 11;
        return null;
    }
}
 
getStepBacks kürzen auf return birthtime/2

in findBy(int birthMonth, int birthTime) kannst du das if ersetzen mit (birthMonth+12 - steps) & 12 (wenn ich mich nicht verrechnet hab, ab besten einmal testen...)

Und dann alles direkt in die Chi-Klasse :)

getChiByMonth kann man dann lösen mit Map oder Ordinal, ist kürzer und schneller.
 
getStepBacks kürzen auf return birthtime/2

in findBy(int birthMonth, int birthTime) kannst du das if ersetzen mit (birthMonth+12 - steps) & 12 (wenn ich mich nicht verrechnet hab, ab besten einmal testen...)

Und dann alles direkt in die Chi-Klasse :)

getChiByMonth kann man dann lösen mit Map oder Ordinal, ist kürzer und schneller.
Ich habe für beide Anpassungen komplett andere Ergebnisse raus.

Was meinst du den mit Ordinal?
 
Ich habe für beide Anpassungen komplett andere Ergebnisse raus.
Oh, bei ersten muss es (birthtime-1)/2 sein, hab übersehen das bei deinen if's die untere Grenze exklusiv und die obere inklusive ist...

Oh, und in der Rechnung sollte es ein % und kein & sein, damit kommt da natürlich Unsinn raus -.-

Was meinst du den mit Ordinal?
https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#ordinal(), entspricht der Position der Deklaration und im values-Array.
 
Oh, bei ersten muss es (birthtime-1)/2 sein, hab übersehen das bei deinen if's die untere Grenze exklusiv und die obere inklusive ist...

Oh, und in der Rechnung sollte es ein % und kein & sein, damit kommt da natürlich Unsinn raus -.-


https://docs.oracle.com/javase/7/docs/api/java/lang/Enum.html#ordinal(), entspricht der Position der Deklaration und im values-Array.
So jetzt sind wir ein Schritt weiter. Die erste Anpassung klappt, die zweite nicht.

Code:
    private Chi findBy(int birthMonth, int birthTime){
        int steps =    getStepBacks(birthTime);
//        if (steps > birthMonth) {
//            steps = steps - birthMonth;
//            steps = Chi.values().length-steps;
//            return getChiByMonth(steps);
//        }else {
//            return getChiByMonth(birthMonth-steps);
//        }
        int result = (birthMonth+12 - steps) & 12;
        return Chi.values()[result];
    }
Hiermit bekomme ich diese Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 12
Also bei der zweiten Anpassung gibt der allgemein ein anderer Wert an wie ich erwarte.

Und wegen dem Ordinal, soll ich das so machen

Code:
    private Chi getChiByMonth(int month) {
        for (Chi chi : Chi.values()) {
            if (chi.ordinal()==month) {
                return chi;
            }
        }
        return null;
    }
Hast du Tipps für mich wie ich solche Optimiereungen sehen kann?
 
Hiermit bekomme ich diese Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 12
Das & ersetzen mit % :)

Und wegen dem Ordinal, soll ich das so machen

private Chi getChiByMonth(int month) {
for (Chi chi : Chi.values()) {
if (chi.ordinal()==month) {
return chi;
}
}

return null;
}
Ne, wenn man eine Schleife nutzt, war deine Variante passend, wenn man ordinal nutzen will, würde man das direkt als Index für das Array nutzen, dafür müsste an aber ein eindeutiges Mapping von ordinal<=>month haben. Dann wäre das etwa Chi.values()[month]. In deinem Fall müsste man aber vermutlich noch Monat auf Ordinal Mappen, wenn ich das oben richtig sehe entspricht Monat 11 =>Ordinal 0, Monat 12=>1, 0=>2, usw ...
 
Das & ersetzen mit % :)



Ne, wenn man eine Schleife nutzt, war deine Variante passend, wenn man ordinal nutzen will, würde man das direkt als Index für das Array nutzen, dafür müsste an aber ein eindeutiges Mapping von ordinal<=>month haben. Dann wäre das etwa Chi.values()[month]. In deinem Fall müsste man aber vermutlich noch Monat auf Ordinal Mappen, wenn ich das oben richtig sehe entspricht Monat 11 =>Ordinal 0, Monat 12=>1, 0=>2, usw ...
Ok jetzt gehts, ist zwar um ein Index versetz, ich habe zu dem Steps einfach 1 addiert.

Code:
private Chi findBy(int birthMonth, int birthTime){
        int steps =    getStepBacks(birthTime);
        int result = (birthMonth+12 - steps+1) % 12;
        return Chi.values()[result];
    }
Und ja Monat 11 wird zum ordinal 0 hinzugefügt,etc.
 
Ich würde getChiByMonth schon da lassen, dann bleiben die Methoden auf einer Abstraktionsebene.


findBy rechnet dann nur mit Monaten und Verschiebung (=fachliches Detail), getChiByMonth sorgt für das Mapping Month<=>ordinal (=technisches Detail).
 
Hi Mr Brown,

ich habe noch eine weitere Herausforderung und zwar will ich immer Paare zusammen haben.

12318

Zum Beispiel:
Id 1 kennt Id5 (grün)
Id 2 kennt Id4
Id 4 kennt Id2 (schwarz)
Id 5 kennt Id1 (schwarz)

An sich sollen alle schwarzen und grünen Pfeile abgebildet werden.

Ich habe eine direkte Abbildung über switch case oder if else gemacht.
Code:
switch(chi){
            case MUI: return Chi.DAU
            case NGO: return Chi.TUAT
            case TI: return Chi.HOI
            case THIN: return Chi.TY
            case MAO: return Chi.SUU
            case THAN: return Chi.DAN
            case DAN: return Chi.THAN
            case DAU: return Chi.MUI
            case TUAT: return Chi.NGO
            case HOI: return Chi.TI
            case TY: return Chi.THIN
            case SUU: return Chi.MAO
            default: return null
        }
Hast du eine Idee wie man das anders schön machen kann? Vorallem gefällt mir der default case mit return null nicht.
 
Man könnte auch da ne Map<Chi,Chi> nutzen, dann wäre es nur ein return get(chi)


throw new AssertionError(...) :)
Guten morgen MrBrown,

beim weiterentwickeln habe ich erst gemerkt, dass der Januar nicht in dem Kacheln fest ist, ich muss ess eher dynamisch machen, da es sich oftmals ändert.

Ist es besser in eine Map zu machen und mit Remainder vorzugehen oder?
 
Also Initial ist der Januar auf Id 3, aber später wechselt es zu Id 12 und andere. Aber jedes mal wenn es sich ändert weiss ich das. An sich brauche ich eher ein Zeiger, der die Monaten mitverschiebt.

Wie kann man das berechnen lassen, wenn ich es nicht in eine Map mache?
Aber selbst mit der Map hätte ich je nach Id immer durchiteriert und die Monate neugesetzt.

Was ist dein Vorschlag?
 
Einfach die "Verschiebung" bei der Berechnung, die du ja schon hast, zusätzlich abziehen/addieren
@mrBrown , Stimmt :)

Was ist wenn ich nicht weiß um wieviele Schritte ich vor oder zurückbewegen, ich weiss nur auf welchen Kachelnamen ich es setzten
Code:
    public Chi resetJanuaryToChi(int steps) {
        int index = (Chi.DAN.getValue()+12+steps)%12;
        return Chi.values()[index];
    }

    public Chi resetJanuaryToChi(Chi newChi) {
        int index = (Chi.DAN.getValue()+12-3)%12;
        return Chi.values()[index];
    }
soll?

Die erste Methode ist klar, aber ich benötige die zweite Methode. Ich habe immer fix bei Chi.DAN den Januar und will anhand von dem neu gewählten Chi den Januar setzen. Wie bekomme ich den Abstand her?
 
Zuletzt bearbeitet:
Passende Stellenanzeigen aus deiner Region:

Neue Themen

Oben