25 im Quadrat (Simulationen)
Auf zwölf Karten sind die ersten natürlichen Zahlen gedruckt (1, 2, ..., 12). Die zwölf Karten werden in einem Quadrat angeordnet, sodass die Mitte des Quadrates leer bleibt, aber auf den vier Kanten je vier Karten liegen:
Die Summe der Kartenwerte auf jeder Kante soll nun 25 ergeben. Gesucht ist also eine Anordnung, bei der für jede Kante alle Werte zusammengezählt den Wert 25 ergeben.
- Geben Sie eine Lösung aus.
- Geben Sie die Anzahl der Lösungen aus.
- Geben Sie alle Lösungen aus. (Achtung: Es sind viele!)
Tipp: Auch wenn das Aufzählen aller 12! Möglichkeiten (ca. 480 Millionen Fälle) lange nicht der effizienteste Algorithmus ist, ist es für einen heutigen PC in wenigen Minuten zu schaffen.
0 Kommentare
3 Lösung(en)
/**
* 12 Karten im Quadrat anlegen, sodass sich die Kantensumme 25 ergibt.
* @author Philipp Gressly (phi@gressly.ch)
*/
public class TwentyFive {
public static void main(String[] args) {
new TwentyFive() . top(); }
int [] actVector = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
int GESUCHTE_SUMME = 25;
int gefundeneLoesungen = 0;
/* Positionen:
* 0 1 2 3
* 4 7
* 5 8
* 6 9 10 11
*/
void top() {
long startTime = System.currentTimeMillis();
checkAll();
long endTime = System.currentTimeMillis();
System.out.println("Zeit in Sekunden: " + (endTime - startTime) / 1000);
}
void checkAll() {
System.out.println("Total sind 479001600 Positionen zu pruefen");
while(! lastPossibility()) {
checkPossibility();
nextPossibility(); }
}
/**
* Aufsteigend nach "Stellenwert" (Analog 10-er system) die
* naechste Zahl finden.
* 4 6 2 3 1 12 10 11 5 9 8 7 -> 4 6 2 3 1 12 10 11 5 9 7 8
* Dieser Algorithmus wird beschrieben in
* Knuth, The Art of Cuputer Programming Volum 4 Facsile 2.
* ISBN: 978 0201 85393-3 Addison-Wesley.
* Kap. 7.2.1.2 "Generating all permutations (Algorithm L).
*/
void nextPossibility() {
// Suche von rechts erstes erhoehbares Zeichen
int actPos = 11;
while(actPos >= 0) {
int nextAtPos = naechsteMoeglichkeitAbPosition(actPos);
if(nextAtPos > actVector[actPos]) {
// ZeichenErhoehen ...
actVector[actPos] = nextAtPos;
//.. und ab hier rechts initialisieren
initialisiereAbPos(actPos + 1 );
return; }
actPos = actPos - 1; }
//Alles durchprobiert.
throw new IndexOutOfBoundsException("Keine weiteren Kombinationen"); }
void initialisiereAbPos(int pos) {
while(pos < 12 ) {
actVector[pos] = kleinstesFreiesZeichen(pos - 1);
pos = pos + 1; }
}
/**
* Pruefe, ob das zeichen "res" bis zur Position "bisPos" bereits auftaucht.
*/
boolean zeichenExistiertBisPos(int res, int bisPos) {
int a = 0;
while(a <= bisPos) {
if(actVector[a] == res) {
return true; }
a = a+1; }
return false; }
int kleinstesFreiesZeichen(int bisPos) {
int res = 0;
while(res <= bisPos + 1) {
if(zeichenExistiertBisPos(res, bisPos)) {
res = res + 1; }
else {
return res; }
}
return -1; } //dies darf nicht passieren.
int naechsteMoeglichkeitAbPosition(int pos) {
int res = actVector[pos] + 1;
while(res <= 11) {
if(zeichenExistiertBisPos(res, pos - 1)) {
res = res + 1;}
else {
return res; }
}
return -1; } // Das bedeutet: hoechstes erreicht.
/**
* Pruefe, ob die aktuelle Position dem 25er Kriterium genuegt.
*/
void checkPossibility() {
if (summePos(0, 1, 2, 3) != GESUCHTE_SUMME) {
return; }
if(summePos(0, 4, 5, 6) != GESUCHTE_SUMME) {
return; }
if(summePos(3, 7, 8, 11) != GESUCHTE_SUMME) {
return; }
if(summePos(6, 9, 10, 11) != GESUCHTE_SUMME) {
return; }
this.gefundeneLoesungen = this.gefundeneLoesungen + 1;
System.out.println("Loesung nr: " + gefundeneLoesungen + "\n" + this); }
int summePos(int i, int j, int k, int l) {
return actVector[i] + actVector[j] + actVector[k] + actVector[l] + 4; }
public String toString() {
return (actVector[0]+1) + " " + (actVector[1]+1) + " " + (actVector[2]+1) + " " + (actVector[3]+1) + "\n" +
(actVector[4]+1) + " " + (actVector[7]+1) + "\n" +
(actVector[5]+1) + " " + (actVector[8]+1) + "\n" +
(actVector[6]+1) + " " + (actVector[9]+1) + " " + (actVector[10]+1) + " " + (actVector[11]+1) + "\n" ; }
/**
* last = 12 11, 10, 9, ..... 1
* at pos 0 1 2 .... 11
*/
boolean lastPossibility() {
boolean result = true;
int pos = 0;
while(pos <= 11) {
if(actVector[pos] != 12 - pos ) {
return false; }
pos ++;
}
return result;
}
} // end of class TwentyFive
Lösung von: Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch)
// NET 6.x | C# 10.x | VS-2022
var cards = new Cards();
Console.WriteLine(cards); // Anzahl Lösungen und die erste Lösung
cards.PrintSolutions(); // alle Lösungen (5248)
public class Cards {
private readonly List<int> _lst = Enumerable.Range(1, 12).ToList();
public Cards() => GetPermutations(_lst, 0, _lst.Count - 1);
public int NumberOfSolutions { get; private set; }
public List<List<int>> Solutions { get; private set; } = new();
public void PrintSolutions() => Enumerable.Range(0, NumberOfSolutions).ToList().ForEach(x => Console.WriteLine(GetMatrix(x)));
private void GetPermutations(List<int> arr, int k, int m) {
if (k == m) {
if (arr.Take(4).Sum() == 25 && arr.Skip(3).Take(4).Sum() == 25 &&
arr.Skip(6).Take(4).Sum() == 25 && arr.Skip(9).Take(3).Sum() + arr[0] == 25) {
NumberOfSolutions++;
Solutions.Add(new(arr));
}
}
else
for (int i = k; i <= m; i++) {
(arr[k], arr[i]) = (arr[i], arr[k]);
GetPermutations(arr, k + 1, m);
(arr[k], arr[i]) = (arr[i], arr[k]);
}
}
private string GetMatrix(int n) {
var f = Solutions[n];
var r1 = $"{f[0]:00} {f[1]:00} {f[2]:00} {f[3]:00}\n";
var r2 = $"{f[11]:00} {f[4]:00}\n";
var r3 = $"{f[10]:00} {f[5]:00}\n";
var r4 = $"{f[9]:00} {f[8]:00} {f[7]:00} {f[6]:00}\n";
return r1 + r2 + r3 + r4;
}
public override string ToString() => $"\nAnzahl Lösungen: {NumberOfSolutions}\n{GetMatrix(0)}";
}
Lösung von: Jens Kelm (@JKooP)
// C++ 14 | VS-2022
#include <iostream>
#include <algorithm>
int main() {
int c[]{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
auto n{ 0 };
do {
if (c[0] + c[1] + c[2] + c[3] == 25 &&
c[3] + c[4] + c[5] + c[6] == 25 &&
c[6] + c[7] + c[8] + c[9] == 25 &&
c[9] + c[10] + c[11] + c[0] == 25) {
n++;
printf("%02u %02u %02u %02u\n", c[0], c[1], c[2], c[3]);
printf("%02u %02u\n", c[11], c[4]);
printf("%02u %02u\n", c[10], c[5]);
printf("%02u %02u %02u %02u\n\n", c[9], c[8], c[7], c[6]);
}
} while (std::next_permutation(c, c + 12));
std::cout << "number of solutions: " << n << "\n";
}
Lösung von: Jens Kelm (@JKooP)
Verifikation/Checksumme:
Total gibt es 5248 Möglichkeiten (inklusive aller Drehungen, Spiegelungen und Vertauschungen von zwei Karten auf der Kante).
Nach dem "Wegdividieren" aller Ähnlichkeiten bleiben 41 grundverschiedene Lösungen.
Aktionen
Neue Lösung hinzufügen
Bewertung
Durchschnittliche Bewertung:
Meta
Zeit: | 2-4 |
Schwierigkeit: | k.A. |
Webcode: | ydd3-8ozc |
Autor: | Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch) |