Codewars Lösung | Let's do a fun graph


coden
Codewars. Achieve mastery through challenge.
Daniel Kaser|7. November 2024
4 min.

Inhalt

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

Die Fakten:

Plattform:codewars.com
Name:Let's do a fun graph
Level:6 kyu
Sprache:TypeScript

Beschreibung:

You have done some data collection today and you want the data to be well presented by a graph so you have decided to make a quick diagram. Suppose that for this kata your data is presented by an array by their value eg [10,5,3,1,4], then you must present your data as follows:


for data = [10,5,3,1,4] :
 ____ ........................ ^ 10
|    |........................ | 9
|    |........................ | 8
|    |........................ | 7
|    |........................ | 6
|    | ____ .................. | 5
|    ||    |............ ____  | 4
|    ||    | ____ ......|    | | 3
|    ||    ||    |......|    | | 2
|    ||    ||    | ____ |    | | 1
|    ||    ||    ||    ||    | | 0

GOOD TO KNOW :

  • Each bar is always of width 6.

  • The vertical axis must be surrounded with one space character on each side.

  • No trailing spaces on any line.

  • For this kata we use :

    • the following characters : '_', ' ', '|', '.', '^'.
    • some numbers.
  • Return type :

    • Your code must return a string consisting of the lines joined by \n.
    • [] and [0] has different returns "" and " ____ ^ 0"

CRITERIA :

  • The length of the array is always less than 50.
  • The numbers in data are always < 50
  • The numbers in data are always positive

GOOD LUCK :)

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

Zuerst sollten wir herausfinden, welche Zahl im Input-Array die größte ist.

Schritt 2

Außerdem brauchen wir eine Variable für unser Ergebnis.

Schritt 3

Als Nächstes brauchen wir einen (vertikalen) Loop.

Schritt 4

Mit diesem loopen wir durch alle Zahlen bis zum Maximum, am besten rückwärts!

Schritt 5

Wir werden eine Variable brauchen, um die Zeichen jeder Ebene zu speichern.

Schritt 6

Dann brauchen wir einen zweiten (horizontalen) Loop.

Schritt 7

Mit dem zweiten Loop loopen wir durch die Zahlen im Input-Array.

Schritt 8

Für jede Zahl hängen wir die nötigen Zeichen an unsere Ebenen-Variable.

Schritt 9

Abhängig davon, ob die Zahl größer, kleiner oder gleich der aktuellen Ebenen-Zahl ist.

Schritt 10

Nach dem zweiten Loop noch die Achse: Wenn die aktuelle Ebene die oberste ist, hängen wir ein ^ an, sonst ein |.

Schritt 11

Hinten noch die aktuelle Ebenen-Zahl anhängen.

Schritt 12

Dann können wir unsere fertige aktuelle Ebene an unser Ergebnis-Array anhängen.

Schritt 13

Nach dem zweiten Loop nur noch das Ergebnis als String mit "\n" verbunden zurückgeben.

Code

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

Lösungsschritte
Meine erste Zeile (ich habe arr in nums umbenannt):
export function graph(nums: number[]): string {
Dann ermitteln wir das Maximum im Input-Array und initialisieren unser Ergebnis-Array:
const result: string[] = [];
const max = Math.max(...nums);
Dann der erste (vertikale) Loop:
  for (let level = max; level >= 0; level--) {

Wir loopen hier rückwärts. Also vom Maximum bis zur 0.

Jetzt können wir schon mal die Achse vorbereiten und unsere Variable für die aktuelle Zeile erstellen:
const axis = level === max ? " ^ " : " | ";
let row = "";
Dann der zweite (horizontale) Loop durch die Zahlen im Input-Array:
    for (const num of nums) {
Jetzt die Bedingungen:
      if (num === level) row += " ____ ";
      if (num > level) row += "|    |";
      if (num < level) row += "......";
    }

Ich finde if...elseif...else und die ganzen geschweiften Klammern nicht besonders sexy. Darum erstelle ich hier für jeden Fall eine eigene if-Bedingung.

Nach dem zweiten Loop noch die Achse an die aktuelle Zeile und die aktuelle Zeile ans Ergebnis anhängen:
    row += axis + level;
    result.push(row);
  }
Zum Schluss das Ergebnis nach dem ersten Loop nur noch als String "\n"-getrennt zurückgeben:
  return result.join("\n");
}
Voilá! 💪

Fragen?

Komplettlösung
export function graph(nums: number[]): string {
  const result: string[] = [];
  const max = Math.max(...nums);

  for (let level = max; level >= 0; level--) {
    const axis = level === max ? " ^ " : " | ";
    let row = "";

    for (const num of nums) {
      if (num === level) row += " ____ ";
      if (num > level) row += "|    |";
      if (num < level) row += "......";
    }

    row += axis + level;
    result.push(row);
  }

  return result.join("\n");
}

Feedback

Schreib mir!