Codewars Lösung | Is Sator Square?


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|20. Juni 2024
3 min.

Inhalt

  1. Die Fakten
  2. Beschreibung
  3. Lösung
    1. Pseudo-Code
    2. Code
  4. Feedback

Die Fakten:

Plattform:codewars.com
Name:Is Sator Square?
Level:7 kyu
Sprache:TypeScript

Beschreibung:

A Discovery

One fine day while Farmer Arepo Tenaciously Labored at Turning the soil, he discovered a field that was scattered with strange stone tablets. Noticing they were carved with letters in a square pattern, he wisely kept them in case some might be special.

Your Task

Please help Farmer Arepo by inspecting each tablet to see if it forms a valid Sator Square!

The Square

is a two-dimentional palindrome, made from words of equal length that can be read in these four ways:

    1)    left-to-right    (across)
    2)    top-to-bottom    (down)
    3)    bottom-to-top    (up)
    4)    right-to-left    (reverse)

An Example

Considering this square:

    B A T S
    A B U T
    T U B A
    S T A B

Here are the four ways a word (in this case "TUBA") can be read:

                         down
                          ↓
           B A T S    B A T S    B A T S    B A T S
           A B U T    A B U T    A B U T    A B U T ← reverse
  across → T U B A    T U B A    T U B A    T U B A
           S T A B    S T A B    S T A B    S T A B
                                   ↑
                                   up

IMPORTANT:

  • In a true Sator Square, ALL of its words can be read in ALL four of these ways.
  • If there is any deviation, it would be false to consider it a Sator Square.

Some Details

  • tablet (square) dimensions range from 2x2 to 33x33 inclusive
  • all characters used will be upper-case alphabet letters
  • there is no need to validate any input

Input

  • an N x N (square) two-dimentional matrix of uppercase letters

Output

  • boolean true or false whether or not the tablet is a Sator Square

Enjoy!

...and please consider one of the following kata to solve next:

Quelle: codewars.com

Lösung

Pseudo-Code

Wie immer gibt's reichlich Varianten, hier ist eine meiner.

Erst die Lösungsschritte in Pseudo-Code. Los geht’s:

Lösungsschritte
Schritt 1

Um alle Reihen bzw. Spalten zu durchlaufen brauchen wir einen Loop.

Schritt 2

Dann können wir alle 4 Optionen erst mal jeweils in einer Variablen speichern.

Schritt 3

leftToRight: easy, einfach die aktuelle (i-te) Reihe bzw. das aktuelle Element.

Schritt 4

topToBottom: das ist jeweils der i-te Buchstabe jeder Reihe.

Schritt 5

bottomToTop: das ist jeweils der i-te Buchstabe jeder Reihe von hinten bzw. rechts, spiegelverkehrt.

Schritt 6

rightToLeft: das ist die aktuelle Reihe von hinten bzw. unten, spiegelverkehrt.

Code

Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:

Lösungsschritte
Meine erste Zeile:
export function isSatorSquare(tablet: string[][]): boolean {
Erst der Loop:
  for (let i = 0; i < tablet.length; i++) {

Ein stinknormaler Standard-For-Loop.

Dann die leftToRight-Variable:
const leftToRight = tablet[i].join("");
Als Zweites die topToBottom-Variable:
const topToBottom = tablet.map((row) => row[i]).join("");

Hier mappen wir durch jedes Element, also jede Reihe und geben nur den jeweils i-ten Buchstaben zurück. Wir erhalten jeden Buchstaben der aktuellen (i-ten) Spalte.

Jetzt die bottomToTop-Variable:
const bottomToTop = tablet
  .slice()
  .map((row) => row[row.length - 1 - i])
  .reverse()
  .join("");

Hier kommen wir von hinten, also rechts, indem wir vom Index des letzten Buchstaben jeder Reihe jeweils i abziehen. Dann drehen wir das Ganze mit .reverse() um.

ACHTUNG
Nicht vergessen hier mit .slice() vorher eine Kopie zu erstellen, denn .reverse() mutiert das Array!
Und zum Schluss die rightToLeft-Variable:
const rightToLeft = tablet[tablet.length - 1 - i].slice().reverse().join("");

Hier kommen wir von unten, indem wir vom Index der letzten Reihe i abziehen. Wir drehen das Ganze wieder mit .reverse() um und erstellen vorher die Kopie mit .slice().

Jetzt können wir unsere Ergebnisse logisch überprüfen:
    if (leftToRight !== topToBottom) return false;
    if (topToBottom !== bottomToTop) return false;
    if (bottomToTop !== rightToLeft) return false;
  }

Hier gibt es viele Möglichkeiten dies zu tun. Diese finde ich am lesbarsten. Keep it simple!

Sollte eines unserer Ergebnisse nicht mit den anderen übereinstimmen, geben wir false zurück.

Ansonsten true:
  return true;
}

Voilá! 💪

Fragen?

Komplettlösung
export function isSatorSquare(tablet: string[][]): boolean {
  for (let i = 0; i < tablet.length; i++) {
    const leftToRight = tablet[i].join("");
    const topToBottom = tablet.map((row) => row[i]).join("");
    const bottomToTop = tablet
      .slice()
      .map((row) => row[row.length - 1 - i])
      .reverse()
      .join("");
    const rightToLeft = tablet[tablet.length - 1 - i]
      .slice()
      .reverse()
      .join("");

    if (leftToRight !== topToBottom) return false;
    if (topToBottom !== bottomToTop) return false;
    if (bottomToTop !== rightToLeft) return false;
  }

  return true;

Feedback

Schreib mir!