JavaScript Anzahl der unterschiedlichen Android Pin Muster berechnen?

n/a

Banned
Registriert
Feb. 2025
Beiträge
673
Irgendwie habe ich gerade Brett vor Kopf oder es liegt an den Temperaturen :heul:

Wie kann ich denn berechnen, wie viele unterschiedliche Muster es in einem 2x2 Grit gibt, wenn jeder Path mind. 3 lang sein muss?

Mein Code spuckt 14 aus, es sollten aber 24 verschiedene Möglichkeiten (Wege) geben, wenn ich mir nicht irre

Möglicherweise habe ich eine Eigenheit von JS übersehen?

Javascript:
calcPaths(2, 2);

function calcPaths(n, m) {
  let arr = [];
  for (let i = 0; i < n; i++) {
    let a = [];
    for (let j = 0; j < m; j++) {
      a.push(i * m + j + 1);
    }
    arr.push(a);
  }
  console.log(arr);
  console.log(solvePath(arr, new Set(), 3, 0));
  // 123 (1.)
  // 124 (2.)
  // 132 (3.)
  // 134 (4.)
  // 142 (5.)
  // 143 (6.)
  // 213 (7.)
  // 214 (8.)
  // 231 (9.)
  // 234 (10.)
  // 241 (11.)
  // 243 (12.)
  // 312 (13.)
  // 314 (14.)
  // 321 (15.)
  // 324 (16.)
  // 341 (17.)
  // 342 (18.)
  // 412 (19.)
  // 413 (20.)
  // 421 (21.)
  // 423 (22.)
  // 431 (23.)
  // 432 (24.)
}

function solvePath(arr, path_set, n, idx) {
  if (n <= 0) {
    return 0;
  }
  let r = 0;
  for (let i = parseInt(idx / arr[0].length); i < arr.length; i++) {
    for (let j = parseInt(idx % arr[0].length); j < arr[i].length; j++) {
      idx++;
      let v = arr[i][j];
      if (!path_set.has(v)) {
        let set = new Set(path_set);
        set.add(v);
        r += solvePath(arr, path_set, n - 1, idx) + 1;
      }
    }
  }
  return r;
}
 
n/a schrieb:
2x2 Grit gibt, wenn jeder Path mind. 3
Sagen wir mal die Dimension des Grid ist n = 2 und der pfad exakt p = 3 lang
dann gibt es im grid n^2 Punkte. und du willst alle einzigartigen Permutationen
(bei nicht quadratischen feldern n*m anstelle von n^2;))

das ist dann (n^2)! / (n^2 - p)!
also 4! / (4-3)! =24

Python:
from itertools import permutations

print(len(list(permutations('1234', 3))))
Ergänzung ()

und von hand implementiert kann das so aussehen.
Python:
def perm_count(n, p):
    count = 1
    for i in range(p):
        count *= (n - i)
    return count

oder du implementierst die formel wie ich sie oben beschrieben habe
Python:
def factorial(x):
    result = 1
    for i in range(2, x+1):
        result *= i
    return result

def permutation(n, p):
    return factorial(n)
Ergänzung ()

ups. war auch ein bisschen dumm und habe deinen Code und den JS teil nicht gelesen.
Aber ich denke die erklaerung oben dürfte reichen?
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: n/a
Also da ist vieles im Argen, deswegen nur ein paar Tipps. Debugge das Ding doch einfach mal Schritt für Schritt oder hau überall ein paar Ausgaben raus, damit du verstehst/lernst wie es sich verhält.

Javascript:
  if (n <= 0) {
    return 0;
  }
Wenn du einfach mal debuggst, wie oft er das Ende erreicht, dann sind es bei dir 4. Nicht 14.
Die 14 enthalten vermutlich jeden einzelnen Schritt.

Bei dir kommen folgende Pfade raus. Alle sind aufsteigend, weil dein Code auch nur "vorwärts" geht.
// 123 (1.)
// 124 (2.)
// 134 (4.)
// 234 (10.)

Und was genau passiert hier mit dem "set"? 🤷‍♂️
Javascript:
        let set = new Set(path_set);
        set.add(v);
        r += solvePath(arr, path_set, n - 1, idx) + 1;
 
  • Gefällt mir
Reaktionen: n/a und madmax2010
n/a schrieb:
ist es eine hausaufgabe aus der uni oder spass?
madmax2010 schrieb:
das ist dann (n^2)! / (n^2 - p)!
das ist alles was du implementieren musst.
auch in Hinblick auf
n/a schrieb:
später möchte ich 4x4 berechnen, wobei die Pfade mind. 4 lang sein sollen (also auch länger sein dürfen)

Im Abi hatten wir das damals mit in statistik / "wahrscheinlichkeitsrechnung" - Die Casio taschenrechner haben dafuer sogar eine Taste.
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: n/a
Wo bin ich hier schrieb:
Und was genau passiert hier mit dem "set"?
Danke, übersehen...

Seltsamerweise kommt bei beiden Varianten das Gleiche raus 😬

Wo bin ich hier schrieb:
Bei dir kommen folgende Pfade raus. Alle sind aufsteigend, weil dein Code auch nur "vorwärts" geht.
Genau... Die Simulation soll auch "rückwärts" gehen... aber das dann planvoll

madmax2010 schrieb:
ist es eine hausaufgabe aus der uni oder spass?
Eigentlich hatte ich einen Artikel auf Reddit über die Anzahl der Pattern bei Smartphones gelesen, und mir dann gedacht, das machste mal nach

Also irgendetwas dazwischen

madmax2010 schrieb:
das ist alles was du implementieren musst
Das ist eine "geschlossene Formel" (glaube, man nennt es so...) aber eigentlich wollte ich jede einzelne Permutation, die infragekommt

madmax2010 schrieb:
Im Abi hatten wir das damals mit in statistik / "wahrscheinlichkeitsrechnung"
Wir, glaube ich, auch... Wahrscheinlichkeitsbäume haben wir gemalt... nicht direkt im Abi, aber im Unterricht

Ich glaube, ich schmeiße den Ansatz weg und mache noch mal neu
 
madmax2010 schrieb:
Im Abi hatten wir das damals mit in statistik / "wahrscheinlichkeitsrechnung"
Haben wir es hier nicht eher mit Fakultäten/Kombinatorik zu tun?

Hab Euren Code nicht gelesen, weil ich beinahe Null Programmierkenntnisse habe, aber da steckt hoffentlich mit drin, dass man bei den Mustern auf den Punkten

123
456
789

auch von der 1 zur 6 kommt. Also, auf direktem Pfad zwischen 4 und 5 hindurch.
 
Zuletzt bearbeitet: (Es ist so warm, ich zähle schon wie Ash am Ende von Army of Darkness.)
  • Gefällt mir
Reaktionen: madmax2010
Man kann jedes Muster dreimal um 90° drehen. 156 wird zu 354, 952 und 756.
 
  • Gefällt mir
Reaktionen: n/a
Ja.
 
  • Gefällt mir
Reaktionen: n/a
So es geht jetzt... auch wenn es nicht die schnellste Implementierung sein wird...

Javascript:
calcPaths(2, 2, 1);
calcPaths(2, 2, 2);
calcPaths(2, 2, 3);
calcPaths(2, 3, 2);

function calcPaths(n, m, len) {
    let arr = [];
    for (let i = 0; i < n; i++) {
        let a = [];
        for (let j = 0; j < m; j++) {
            a.push(i * m + j + 1);
        }
        arr.push(a);
    }
    console.log(arr);
    console.log(solvePath(arr, new Set(), len));
}

function solvePath(arr, path_set, n) {
    if (n <= 0) {
        return 1;
    }
    let r = 0;
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr[i].length; j++) {
            let v = arr[i][j];
            if (!path_set.has(v)) {
                let set = new Set(path_set);
                set.add(v);
                r += solvePath(arr, set, n - 1);
            }
        }
    }
    return r;
}

u. a. dieses new Set() bereitet mir etwas Sorge
 
War doch nicht richtig... und verstehe ich jetzt nicht mehr... Bei 3x3 sollten die möglichen Kombinationen 389497 sein, aber bei mir sind es 442008:

Quelle

Sieht jemand den Käfer?

Javascript:
function calcPaths(n, m, min_len) {
  let arr = []
  for (let i = 0; i < n; i++) {
    let a = []
    for (let j = 0; j < m; j++) {
      a.push(i * m + j + 1)
    }
    arr.push(a)
  }
  console.log(n, m, min_len, arr)
  let r = 0
  let s = new Set()
  for (let i = min_len; i <= n * m; i++) {
    r += solvePath(arr, s, i)
  }
  console.log(r)
  return r
}

function solvePath(arr, path_set, n) {
  if (
    path_set.size >= n - 1 ||
    arr[0].length * arr[0].length - path_set.size <= 2
  ) {
    return 1
  }
  let r = 0
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      let v = arr[i][j]
      if (!path_set.has(v)) {
        let set = new Set(path_set)
        set.add(v)
        r += solvePath(arr, set, n)
      }
    }
  }
  return r
}

calcPaths(2, 2, 3)
calcPaths(3, 3, 4)
//calcPaths(4, 4, 4)
 
dx1 schrieb:
Man kann jedes Muster dreimal um 90° drehen. 156 wird zu 354, 952 und 756.
Dennoch können nicht-monotone Folgen auftreten, ein Beispiel hast du ja aufgeführt.

Mein Ansatz wäre, einen Graphen zu bauen und den abzugehen. Da gibt es sicherlich auch schon fertige Libraries für Java und die einzige Aufgabe besteht im Prinzip darin, Nachbarschaft/Verbundenheit richtig zu definieren.

n/a schrieb:
Sieht jemand den Käfer?
Bisschen viele n, m und i... das ist nicht gut, das macht den Code schwer lesbar. Lesbarkeit von Code ist neben der Korrektheit mit die Wichtigste Eigenschaft von Code.
Du solltest einzelne Aspekte auch ausgliedern in getrennte Funktionen. Hat den zusätzlichen Vorteil, dass du für diese Funktionen Unittests schreiben kannst. Erleichtert dir selbst auch das konzeptionelle Verständnis davon, was der Code macht. Das beschleunigt die Entwicklung ungemein wenn man viel herumrechnen muss.
 
Zuletzt bearbeitet:
BeBur schrieb:
Bisschen viele n, m und i... das ist nicht gut, das macht den Code schwer lesbar. Lesbarkeit von Code ist neben der Korrektheit mit die Wichtigste Eigenschaft von Code.

Linux coding style schrieb:
LOCAL variable names should be short, and to the point. If you have some random integer loop counter, it should probably be called i. Calling it loop_counter is non-productive, if there is no chance of it being mis-understood.

SCNR,
xpad.c
 
  • Gefällt mir
Reaktionen: Micke und n/a
xpad.c schrieb:
Ist halt offensichtlich falsch angewendet. n/a verwendet fast nur einzelne Buchstaben und Abkürzungen. r für Result zu schreiben ist syntaktisch möglich und semantisch nicht falsch aber von der Sache her (= hochwertigen Code produzieren) falsch - um mal nur ein Beispiel zu nennen.
Mal davon abgesehen ist der Linux coding style guide nicht das Maß aller Dinge. Generell kein Maß für irgendwas außerhalb des Kernels, soweit ich weiß.

Mal ganz davon abgesehen, dass es in Java Iteratoren bzw. list-iteration gibt.
 
Zuletzt bearbeitet:
Das ist schlicht schlechter Code. Da gibt es auch nichts zu verteidigen. Das es keine Metrik gibt ändert daran nichts. Geht auch gar nicht gegen dich, an der Uni lernt man es nicht besser. Schlimm ist das nur, wenn das nicht korrigiert, sondern verteidigt wird.
 
Zurück
Oben