Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

David Scherfgen

Administrator

  • »David Scherfgen« ist der Autor dieses Themas

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

1

21.02.2008, 21:24

#04: "Reisekosten", Geschwindigkeit, 16.03.2008

#04: "Reisekosten"
Typ: Geschwindigkeit
Deadline: 16.03.2008
Abgabe: contest@spieleprogrammierer.de

Bitte beachten:
- Ablauf und Regeln


Auf dem Planeten Wurstulon 7 hat sich der clevere Städteplaner Fulko Bumbanzki ein ganz besonderes öffentliches Schienentransportsystem ausgedacht. Jeder Bahnhof erhält dabei eine eindeutige Nummer von 0 bis N - 1, wobei N die Anzahl der Bahnhöfe ist. Bei fünf Bahnhöfen gibt es also die Nummern 0, 1, 2, 3 und 4.

Die Züge verkehren aber nur nach ganz bestimmten Regeln. Vom Bahnhof Nummer X aus kann man ausschließlich zu den Bahnhöfen mit den folgenden Nummern fahren: X + 7, X - 11 und X * 13. Die Tickets "+7" und "-11" kosten jeweils 1 Sm (Schokomünze), und das Ticket "*13" kostet 2 Sm.

Würde man durch seine Fahrt zu einem Bahnhof mit einer negativen Nummer gelangen, so wird hinten wieder angefangen. Das Umgekehrte gilt für Bahnhöfe mit zu großer Nummer. Fährt man bei 100 Bahnhöfen also beispielsweise vom Bahnhof Nummer 5 zum Bahnhof Nummer 5 - 11 = -6, dann kommt man beim Bahnhof Nummer 94 an. Fährt man vom Bahnhof Nummer 8 zum Bahnhof Nummer 8 * 13 = 104, dann kommt man beim Bahnhof Nummer 4 an. Mathematisch gesprochen wird im Restklassenring modulo N gerechnet.

Bevor das neue System eingeführt wird, soll Fulko Bumbanzki für die Regierung ein Computerprogramm in der Sprache oktán'52.XP schreiben, das ausrechnet, wie teuer die Reise von einem beliebigen Startbahnhof zu einem beliebigen Zielbahnhof mindestens ist. Die Anzahl der Bahnhöfe wird dem Programm ebenfalls als Eingabe mitgeteilt. Durch einen glücklichen Zufall entspricht die Sprache oktán'52.XP auf dem Planeten Wurstulon 7 bis auf einen unbedeutenden Unterschied genau der Sprache C++ auf der Erde (der Datentyp für Fließkommazahlen mit höherer Genauigkeit heißt in oktán'52.XP nicht "double", sondern "knoblauch_muesli").

Deine Aufgabe ist es, diese Funktion für Fulko Bumbanzki in oktán'52.XP, also C++, zu programmieren. Die Funktion soll möglichst schnell sein, da der Computer, auf dem sie laufen soll, extrem langsam ist (dafür hat er aber einen sehr großen Hauptspeicher). Dass mit seinem System jeder Bahnhof von jedem anderen Bahnhof aus erreichbar ist, hat Fulko bereits mathematisch bewiesen - dies kann also vorausgesetzt werden. Die zu schreibende Funktion sieht wie folgt aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
unsigned int travel_costs(unsigned int from, unsigned int to, unsigned int num_stations)
{
  // Liefere die minimalen Reisekosten in Sm,

  // um vom Bahnhof Nummer [from] zum Bahnhof Nummer [to] zu kommen,

  // wenn es [num_stations] Bahnhöfe gibt,

  // die Tickets "+7" und "-11" jeweils 1 Sm kosten und das Ticket "*13" für 2 Sm zu haben ist.

}


Die Anzahl der Bahnhöfe, also der Parameter "num_stations", liegt immer zwischen 1 und 10.000.000 (Wurstulon 7 ist ein sehr großer Planet). Die Parameter "from" und "to" liegen zwischen 0 und "num_stations" - 1. Gefragt sind nur die minimalen Reisekosten, also nicht der eigentliche Weg vom Start zum Ziel.

Ich wünsche viel Erfolg und hoffe, dass diese Aufgabe besser ankommt als die mit den Kreisen. Hier das Testframework:

C-/C++-Quelltext

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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//////////////////////////////////////////////////////////////////////////

// spieleprogrammierer.de-Programmier-Contest #04                       //

// ******************************************************************** //

// Titel: ...... "Reisekosten"                                          //

// Typ: ........ Geschwindigkeit                                        //

// Deadline: ... 16.03.2008                                             //

// Abgabe: ..... contest@spieleprogrammierer.de                         //

// ******************************************************************** //

//                                                                      //

// Aufgabenstellung siehe:                                              //

// https://www.spieleprogrammierer.de/phpBB2/viewtopic.php?t=9138        //

//                                                                      //

//////////////////////////////////////////////////////////////////////////


#include <vector>
#include <string>
#include <iostream>
#include <iomanip>
#include <ctime>

//////////////////////////////////////////////////////////////////////////


// Kompatibilität zu oktán'52.XP herstellen

#ifdef __cplusplus
typedef double knoblauch_muesli;
#endif

//////////////////////////////////////////////////////////////////////////


// maximale Anzahl der Bahnhöfe

const unsigned int MAX_NUM_STATIONS = 10000000;

// Wie lange soll jeder Fall mindestens getestet werden?

// Je länger, desto genauer ist die Zeitmessung.

const knoblauch_muesli NUM_SECONDS_PER_TEST = 1.0;

//////////////////////////////////////////////////////////////////////////


// Hilfsfunktion zum Messen der Zeit

knoblauch_muesli time()
{
    return static_cast<knoblauch_muesli>(clock()) / CLOCKS_PER_SEC;
}

//////////////////////////////////////////////////////////////////////////


// >>> DEINE FUNKTION - BITTE IMPLEMENTIEREN! <<<

unsigned int my_travel_costs(unsigned int from, unsigned int to, unsigned int num_stations)
{
    return 0;
}

//////////////////////////////////////////////////////////////////////////


// Testfall

struct TestCase
{
    TestCase(unsigned int from, unsigned int to, unsigned int num_stations, unsigned int correct_result)
        : from(from), to(to), num_stations(num_stations), correct_result(correct_result)
    {
    }

    unsigned int from;              // Startbahnhof

    unsigned int to;                // Zielbahnhof

    unsigned int num_stations;      // Anzahl der Bahnhöfe

    unsigned int correct_result;    // korrektes Ergebnis

};

//////////////////////////////////////////////////////////////////////////


int main()
{
    // Testfälle vorbereiten

    std::vector<TestCase> test_cases;
    test_cases.push_back(TestCase(0, 0, 1, 0));
    test_cases.push_back(TestCase(0, 1, 2, 1));
    test_cases.push_back(TestCase(1, 13, 100, 2));
    test_cases.push_back(TestCase(5, 6, 10, 3));
    test_cases.push_back(TestCase(1, 169, 1000, 4));
    test_cases.push_back(TestCase(0, 49, 50, 5));
    test_cases.push_back(TestCase(1, 197, 500, 6));
    test_cases.push_back(TestCase(10, 349, 1000, 7));
    test_cases.push_back(TestCase(1, 2193, 5000, 8));
    test_cases.push_back(TestCase(4994, 2193, 5000, 9));
    test_cases.push_back(TestCase(1, 71293, 100000, 10));
    test_cases.push_back(TestCase(1, 71300, 100000, 11));
    test_cases.push_back(TestCase(0, 98102, 100000, 12));
    test_cases.push_back(TestCase(0, 98109, 100000, 13));
    test_cases.push_back(TestCase(12, 8192, 10000, 14));
    test_cases.push_back(TestCase(1, 48506, 100000, 15));
    test_cases.push_back(TestCase(513, 77925, 100000, 16));
    test_cases.push_back(TestCase(103, 77282, 100000, 17));
    test_cases.push_back(TestCase(5001, 500001, 1000000, 18));
    test_cases.push_back(TestCase(1, 5730742, 10000000, 19));
    test_cases.push_back(TestCase(1, 8491849, 10000000, 20));

    std::cout.setf(std::ios::left);
    std::cout << std::setw(10) << "from";
    std::cout << std::setw(10) << "to";
    std::cout << std::setw(15) << "num_stations";
    std::cout << std::setw(10) << "Ergebnis";
    std::cout << std::setw(10) << "Korrekt";
    std::cout << std::setw(10) << "OK?";
    std::cout << std::setw(10) << "Zeit (ms)" << std::endl;
    std::cout << std::string(75, '-') << std::endl;

    // testen und die Zeit messen

    bool all_correct = true;
    for(std::vector<TestCase>::const_iterator it = test_cases.begin();
        it != test_cases.end();
        ++it)
    {
        std::cout << std::setw(10) << it->from;
        std::cout << std::setw(10) << it->to;
        std::cout << std::setw(15) << it->num_stations;

        unsigned int result = 0;
        bool correct = true;

        const knoblauch_muesli t0 = time();
        unsigned int num_iterations = 0;
        knoblauch_muesli t = 0.0;

        // so oft testen,

        // bis NUM_SECONDS_PER_TEST Sekunden vergangen sind

        do
        {
            result = my_travel_costs(it->from, it->to, it->num_stations);
            correct &= result == it->correct_result;

            t = time() - t0;
            ++num_iterations;
        }
        while(t < NUM_SECONDS_PER_TEST);

        all_correct &= correct;

        std::cout << std::setw(10) << result;
        std::cout << std::setw(10) << it->correct_result;
        std::cout << std::setw(10) << (correct ? "Ja" : "Nein");
        std::cout << std::setw(10) << (t / num_iterations * 1000.0) << std::endl;
    }

    std::cout << std::endl << (all_correct ? "Alles OK!" : "So kann die Regierung das nicht akzeptieren!") << std::endl;

    return 0;
}

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

2

21.02.2008, 23:01

Also bei mir kommt diese Aufgabe schonmal definitiv besser an - nicht nur wegen der genialen Beschreibung :D

Mastermind

unregistriert

3

22.02.2008, 01:52

Man verzeihe Ungereimtheiten aufgrund der Uhrzeit. Mögliche Denkfehler und minor Spoiler ahead:




Möglichkeit 1:
Es gibt einen geschlossenen Ausdruck, entfernung lässt dich aufgrund der gesetzmäßigkeiten drekt angeben.

Möglichkeit 2:
Es gibt eine sinnvolle Heuristik für die Entfernung.

Möglichkeit 3:
sonst

Hmm... Klingt eher nach einer Mathe- als nach einer Programmieraufgabe... Was man versuchen könnte, wenn man zu faul ist selbst zu denken, wär eine Heuristik mit einem Maschinenlernverfahren zu bestimmen. Wär sicher interessant.

Mal angenommen es enthält keine Mathe Tricks (Fall 3), dann ist es ein ziemlich hartes Kriterium, wieviele Anfragen für dasselbe N kommen werden. (Fixkosten vs. variable Kosten), was der Aufgabensteller hier nicht angegeben hat.

Szenarionahe Aufgaben wie "nach dem Hinzufügen eines Bahnhofs soll die Preisdatenbank upgedatet werden" gehen eher in Richtung festes, aber beliebiges N. Dann hätte man auch gleich fragen können wer aus *piep* das meiste rausholt. (Will das böse Wort mit F und W hier nicht nennen, falls das als Spoilern angesehen wird).

David Scherfgen

Administrator

  • »David Scherfgen« ist der Autor dieses Themas

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

4

22.02.2008, 08:54

Geht am besten davon aus, dass sich alle Anfragen unterscheiden, was die Anzahl der Bahnhöfe angeht (und natürlich auch Start und Ziel). Ich möchte nicht, dass jemand gewinnt, weil er sich Ergebnisse vom letzten Aufruf merkt und die dann weiter verwendet. Die Lösung soll jedes Mal komplett neu berechnet werden.

5

22.02.2008, 11:21

Ich hab so ein ähnliches Rätsel schon mal gesehen, glaub da gibt nen mathematischen Ansatz.

Ich hab jetzt erst mal nen simplen Ansatz gewählt, der hat sogar fast auf Anhieb geklappt, dauert aber über 5min :D

rootnode

Frischling

Beiträge: 92

Wohnort: Aachen, Pontstraße

Beruf: Student

  • Private Nachricht senden

6

22.02.2008, 12:37

Jaja, die gute NP-Härte ^^
Aber ich hab meinen Ansatz auch schon gefunden.

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

7

22.02.2008, 14:32

Hab auch schon nen funktionierenden Ansatz...


Is natürlich nur begrenzt aussagekräftig, da jeder nen anderes System hat, aber wie sind eure Werte so ca?

Quellcode

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
Release (VS 2005)

1 Sec. je Aufgabe

// €dit: Neu

from      to        num_stations   Ergebnis  Korrekt   OK?       Zeit (ms)
---------------------------------------------------------------------------
0         0         1              0         0         Ja        6.29954e-005
0         1         2              1         1         Ja        7.12058e-005
1         13        100            2         2         Ja        8.90932e-005
5         6         10             3         3         Ja        0.00010178
1         169       1000           4         4         Ja        0.000210425
0         49        50             5         5         Ja        0.000328621
1         197       500            6         6         Ja        0.000571027
10        349       1000           7         7         Ja        0.00101066
1         2193      5000           8         8         Ja        0.00259194
4994      2193      5000           9         9         Ja        0.00504319
1         71293     100000         10        10        Ja        0.013554
1         71300     100000         11        11        Ja        0.0216413
0         98102     100000         12        12        Ja        0.0232148
0         98109     100000         13        13        Ja        0.052521
12        8192      10000          14        14        Ja        0.083375
1         48506     100000         15        15        Ja        0.227531
513       77925     100000         16        16        Ja        0.582751
103       77282     100000         17        17        Ja        0.888099
5001      500001    1000000        18        18        Ja        3.7594
1         5730742   10000000       19        19        Ja        19.5385
1         8491849   10000000       20        20        Ja        21.2766

Alles OK!

big_muff

Alter Hase

Beiträge: 460

Wohnort: Schweiz

Beruf: Informatikstudent (4. Semester)

  • Private Nachricht senden

8

22.02.2008, 17:02

Ich habe mal ein paar aufwendige oder spezielle Testcases erstellt.
Meine Funktion stimmt zwar für alle vordefinierten Testcases, aber ich wäre trotzdem froh wenn mir jemand meine Testcases bestätigen könnte.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
    //bigmuff's Testcases

    test_cases.push_back(TestCase(1250358, 9140287, 10000000, 21));
    test_cases.push_back(TestCase(1, 9140287, 10000000, 22));
    test_cases.push_back(TestCase(5339546, 1588123, 6640162, 23));
    test_cases.push_back(TestCase(4971805, 3783278, 5042105, 23));
    test_cases.push_back(TestCase(1663142, 3633657, 8313554, 23));
    test_cases.push_back(TestCase(1156811, 3514077, 6228554, 24));
    test_cases.push_back(TestCase(3161534, 3260614, 6801046, 24));
    test_cases.push_back(TestCase(9394725, 6873969, 9608835, 24));
    test_cases.push_back(TestCase(9045292, 437535, 9655704, 25));
    test_cases.push_back(TestCase(26480, 4188320, 9978560, 26));
    test_cases.push_back(TestCase(3049806, 7726710, 8456639, 27));
    test_cases.push_back(TestCase(1, 4826809, 4826885, 7));
Nur Idioten halten Ordnung, ein Genie beherrscht das Chaos.[size=7]

[/size]HardFate - Ein Start, Ein Ziel, Viele Wege[size=7]

[/size]Ein Mitglied der VEGeiCoUndGraSonMaWiGeS Bewegung.

David Scherfgen

Administrator

  • »David Scherfgen« ist der Autor dieses Themas

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

22.02.2008, 17:45

@big_muff:
Bei 3049806 => 7726710 und 8456639 Bahnhöfen kriege ich 26 statt 27 raus (liegt es an dir oder an mir?). Ansonsten kann ich alles bestätigen.

@grek40:
Wow, das ist ganz schön schnell!

@Alle:
Hat jemand eine Idee, wie man herausfinden könnte, wie teuer bei N Bahnhöfen die teuerste Strecke ist, die es gibt? Also wie hoch kann das korrekte Ergebnis maximal sein?

grek40

Alter Hase

Beiträge: 1 491

Wohnort: Dresden

  • Private Nachricht senden

10

22.02.2008, 18:32

@ big_muff
Beim vorletzten Testfall hab ich auch 26 und nich 27 raus - ich geh mal davon aus, dass David und ich bis auf Widerruf richtig liegen :)


Ansonsten thnx für die Daten, die bringen auch meine Lösung mal bisschen ins schwitzen (bis zu 727.5 ms im langsamsten Testfall)

Werbeanzeige