Du schreibst Funktionen, die Listen bekommen: zusammenzählen, das Größte finden, eine neue Liste in anderer Reihenfolge bauen, Doppelte entfernen und zwei sortierte Listen zu einer mischen.
Eine Liste hält mehrere Werte in einer Reihe. Jedes Element hat einen Index: Das erste hat den Index 0, das zweite den Index 1. Diese Funktion baut eine neue Liste, in der jede Zahl doppelt so groß ist:
def doubled(numbers) result = [] numbers.each do |number| result << number * 2 end result end puts doubled([3, 4, 5]).inspect # [6, 8, 10] numbers = [3, 4, 5] puts numbers.length # 3 puts numbers[0] # 3, das Element mit dem Index 0 puts numbers[-1] # 5, das letzte
numbers.each do |number| … end geht die Elemente der Reihe nach durch,
result << … hängt hinten an. Wer den Index braucht, zählt selbst:
(0...numbers.length).each do |i| … end läuft mit i von 0 bis zum letzten
Index.
def doubled(numbers): result = [] for number in numbers: result.append(number * 2) return result print(doubled([3, 4, 5])) # [6, 8, 10] numbers = [3, 4, 5] print(len(numbers)) # 3 print(numbers[0]) # 3, das Element mit dem Index 0 print(numbers[-1]) # 5, das letzte
for number in numbers: geht die Elemente der Reihe nach durch,
result.append(…) hängt hinten an. Wer den Index braucht, zählt selbst:
for i in range(len(numbers)): läuft mit i von 0 bis zum letzten Index.
function doubled(numbers) { const result = []; for (const number of numbers) { result.push(number * 2); } return result; } console.log(doubled([3, 4, 5])); // [ 6, 8, 10 ] const numbers = [3, 4, 5]; console.log(numbers.length); // 3 console.log(numbers[0]); // 3, das Element mit dem Index 0 console.log(numbers[numbers.length - 1]); // 5, das letzte
for (const number of numbers) { … } geht die Elemente der Reihe nach
durch, result.push(…) hängt hinten an. Wer den Index braucht, zählt
selbst: for (let i = 0; i < numbers.length; i++) läuft mit i von 0 bis
zum letzten Index.
Die Katas geben eine neue Liste zurück und lassen die, die sie bekommen, wie sie ist.
Schreib eine Funktion list_sum(numbers), die alle Zahlen einer Liste zusammenzählt: list_sum([3, 4, 5]) ergibt 12. Mit einer Schleife, ohne sum.
Wie bei sum_to aus den Schleifen: eine Variable, die bei 0 anfängt, und in der Schleife kommt jede Zahl dazu.
numbers.each do |number| … end geht die Zahlen der Liste der Reihe nach durch.
Schreib eine Funktion list_sum(numbers), die alle Zahlen einer Liste zusammenzählt: list_sum([3, 4, 5]) ergibt 12. Mit einer Schleife, ohne sum.
Wie bei sum_to aus den Schleifen: eine Variable, die bei 0 anfängt, und in der Schleife kommt jede Zahl dazu.
for number in numbers: geht die Zahlen der Liste der Reihe nach durch.
Schreib eine Funktion listSum(numbers), die alle Zahlen einer Liste zusammenzählt: listSum([3, 4, 5]) ergibt 12. Mit einer Schleife, ohne reduce.
Wie bei sumTo aus den Schleifen: eine Variable, die bei 0 anfängt, und in der Schleife kommt jede Zahl dazu.
for (const number of numbers) { … } geht die Zahlen der Liste der Reihe nach durch.
Schreib eine Funktion list_max(numbers), die die größte Zahl einer Liste zurückgibt: list_max([3, 9, 4]) ergibt 9. Die Liste ist nie leer. Ohne max und sort.
Merk dir die bisher größte Zahl in einer Variablen und vergleich jede Zahl mit ihr.
Womit fängst du an? numbers[0] ist die Zahl mit dem Index 0, die erste.
Schreib eine Funktion list_max(numbers), die die größte Zahl einer Liste zurückgibt: list_max([3, 9, 4]) ergibt 9. Die Liste ist nie leer. Ohne max und sorted.
Merk dir die bisher größte Zahl in einer Variablen und vergleich jede Zahl mit ihr.
Womit fängst du an? numbers[0] ist die Zahl mit dem Index 0, die erste.
Schreib eine Funktion listMax(numbers), die die größte Zahl einer Liste zurückgibt: listMax([3, 9, 4]) ergibt 9. Die Liste ist nie leer. Ohne Math.max und sort.
Merk dir die bisher größte Zahl in einer Variablen und vergleich jede Zahl mit ihr.
Womit fängst du an? numbers[0] ist die Zahl mit dem Index 0, die erste.
Schreib eine Funktion count_even(numbers), die zählt, wie viele gerade Zahlen in der Liste stehen: count_even([1, 2, 3, 4]) ergibt 2.
Zählen wie bei den Vokalen: eine Variable, die bei 0 anfängt. Wann ist eine Zahl gerade?
number % 2 == 0 fragt, ob beim Teilen durch 2 nichts übrig bleibt.
Schreib eine Funktion count_even(numbers), die zählt, wie viele gerade Zahlen in der Liste stehen: count_even([1, 2, 3, 4]) ergibt 2.
Zählen wie bei den Vokalen: eine Variable, die bei 0 anfängt. Wann ist eine Zahl gerade?
number % 2 == 0 fragt, ob beim Teilen durch 2 nichts übrig bleibt.
Schreib eine Funktion countEven(numbers), die zählt, wie viele gerade Zahlen in der Liste stehen: countEven([1, 2, 3, 4]) ergibt 2.
Zählen wie bei den Vokalen: eine Variable, die bei 0 anfängt. Wann ist eine Zahl gerade?
number % 2 === 0 fragt, ob beim Teilen durch 2 nichts übrig bleibt.
Schreib eine Funktion contains(items, wanted), die true zurückgibt, wenn wanted in der Liste steht, und sonst false: contains([4, 8, 15], 8) ergibt true. Mit einer Schleife, ohne include? und index.
Geh die Liste durch. Findest du wanted, bist du sofort fertig: return true beendet die Funktion mitten in der Schleife.
Und wenn die Schleife zu Ende ist, ohne dass du es gefunden hast?
Schreib eine Funktion contains(items, wanted), die True zurückgibt, wenn wanted in der Liste steht, und sonst False: contains([4, 8, 15], 8) ergibt True. Mit einer Schleife, ohne in (außer in for … in) und index.
Geh die Liste durch. Findest du wanted, bist du sofort fertig: return True beendet die Funktion mitten in der Schleife.
Und wenn die Schleife zu Ende ist, ohne dass du es gefunden hast?
Schreib eine Funktion contains(items, wanted), die true zurückgibt, wenn wanted in der Liste steht, und sonst false: contains([4, 8, 15], 8) ergibt true. Mit einer Schleife, ohne includes, indexOf und some.
Geh die Liste durch. Findest du wanted, bist du sofort fertig: return true; beendet die Funktion mitten in der Schleife.
Und wenn die Schleife zu Ende ist, ohne dass du es gefunden hast?
Schreib eine Funktion reverse_list(items), die eine neue Liste zurückgibt, mit denselben Elementen in umgekehrter Reihenfolge: reverse_list([1, 2, 3]) ergibt [3, 2, 1]. Ohne reverse.
Der letzte Index einer Liste ist items.length - 1. Zähl von dort herunter bis 0 und häng jedes Element mit << an eine neue Liste an.
Ein Gerüst:
i = items.length - 1 while i >= 0 # items[i] anhängen i -= 1 end
Schreib eine Funktion reverse_list(items), die eine neue Liste zurückgibt, mit denselben Elementen in umgekehrter Reihenfolge: reverse_list([1, 2, 3]) ergibt [3, 2, 1]. Ohne reversed, reverse und [::-1].
Der letzte Index einer Liste ist len(items) - 1. Zähl von dort herunter bis 0 und häng jedes Element mit append an eine neue Liste an.
range(len(items) - 1, -1, -1) zählt vom letzten Index bis 0 herunter.
Schreib eine Funktion reverseList(items), die eine neue Liste zurückgibt, mit denselben Elementen in umgekehrter Reihenfolge: reverseList([1, 2, 3]) ergibt [3, 2, 1]. Ohne reverse und toReversed.
Der letzte Index einer Liste ist items.length - 1. Zähl von dort herunter bis 0 und häng jedes Element mit push an eine neue Liste an.
for (let i = items.length - 1; i >= 0; i--) zählt vom letzten Index bis 0 herunter.
Schreib eine Funktion swap_ends(items), die eine neue Liste zurückgibt, in der das erste und das letzte Element die Plätze getauscht haben: swap_ends([1, 2, 3, 4]) ergibt [4, 2, 3, 1]. Eine Liste mit weniger als zwei Elementen bleibt, wie sie ist.
items.dup ist eine Kopie der Liste. items[-1] ist das letzte Element.
Wenn du result[0] überschreibst, ist der alte Wert weg. Woher nimmst du ihn für hinten?
Schreib eine Funktion swap_ends(items), die eine neue Liste zurückgibt, in der das erste und das letzte Element die Plätze getauscht haben: swap_ends([1, 2, 3, 4]) ergibt [4, 2, 3, 1]. Eine Liste mit weniger als zwei Elementen bleibt, wie sie ist.
list(items) ist eine Kopie der Liste. items[-1] ist das letzte Element.
Wenn du result[0] überschreibst, ist der alte Wert weg. Woher nimmst du ihn für hinten?
Schreib eine Funktion swapEnds(items), die eine neue Liste zurückgibt, in der das erste und das letzte Element die Plätze getauscht haben: swapEnds([1, 2, 3, 4]) ergibt [4, 2, 3, 1]. Eine Liste mit weniger als zwei Elementen bleibt, wie sie ist.
[...items] ist eine Kopie der Liste. items[items.length - 1] ist das letzte Element.
Wenn du result[0] überschreibst, ist der alte Wert weg. Woher nimmst du ihn für hinten?
swap_ends die
Liste, die du bekommst, statt einer Kopie, und gib sie aus, nachdem du die
Funktion aufgerufen hast. Was ist mit der Liste draußen passiert?
Schreib eine Funktion rotate_left(items), die alle Elemente um einen Platz nach links rückt; das erste kommt ans Ende: rotate_left([1, 2, 3, 4]) ergibt [2, 3, 4, 1]. Ohne rotate.
Die neue Liste besteht aus allen Elementen ab dem Index 1 und danach dem Element mit dem Index 0.
Denk an die leere Liste: Sie hat kein erstes Element.
Schreib eine Funktion rotate_left(items), die alle Elemente um einen Platz nach links rückt; das erste kommt ans Ende: rotate_left([1, 2, 3, 4]) ergibt [2, 3, 4, 1].
Die neue Liste besteht aus allen Elementen ab dem Index 1 und danach dem Element mit dem Index 0.
Denk an die leere Liste: Sie hat kein erstes Element.
Schreib eine Funktion rotateLeft(items), die alle Elemente um einen Platz nach links rückt; das erste kommt ans Ende: rotateLeft([1, 2, 3, 4]) ergibt [2, 3, 4, 1].
Die neue Liste besteht aus allen Elementen ab dem Index 1 und danach dem Element mit dem Index 0.
Denk an die leere Liste: Sie hat kein erstes Element.
Schreib eine Funktion ascending(numbers), die true zurückgibt, wenn jede Zahl mindestens so groß ist wie die vor ihr, und sonst false: ascending([1, 3, 3, 8]) ergibt true, ascending([1, 5, 2]) ergibt false. Ohne zu sortieren.
Vergleich jede Zahl mit der vor ihr: numbers[i] mit numbers[i - 1]. Bei welchem i fängst du an?
Ein einziger Schritt abwärts reicht für false. Erst wenn alle Schritte stimmen, ist es true, wie bei contains.
Schreib eine Funktion ascending(numbers), die True zurückgibt, wenn jede Zahl mindestens so groß ist wie die vor ihr, und sonst False: ascending([1, 3, 3, 8]) ergibt True, ascending([1, 5, 2]) ergibt False. Ohne zu sortieren.
Vergleich jede Zahl mit der vor ihr: numbers[i] mit numbers[i - 1]. Bei welchem i fängst du an?
Ein einziger Schritt abwärts reicht für False. Erst wenn alle Schritte stimmen, ist es True, wie bei contains.
Schreib eine Funktion ascending(numbers), die true zurückgibt, wenn jede Zahl mindestens so groß ist wie die vor ihr, und sonst false: ascending([1, 3, 3, 8]) ergibt true, ascending([1, 5, 2]) ergibt false. Ohne zu sortieren.
Vergleich jede Zahl mit der vor ihr: numbers[i] mit numbers[i - 1]. Bei welchem i fängst du an?
Ein einziger Schritt abwärts reicht für false. Erst wenn alle Schritte stimmen, ist es true, wie bei contains.
Schreib eine Funktion remove_duplicates(items), die eine neue Liste zurückgibt, in der jedes Element nur einmal vorkommt, dort, wo es zum ersten Mal stand: remove_duplicates([3, 1, 3, 2, 1]) ergibt [3, 1, 2]. Ohne uniq.
Bau eine neue Liste auf. Bevor ein Element hineinkommt: Steht es schon darin? Das ist deine Kata contains, und hier darfst du include? benutzen.
result << item unless result.include?(item)
Schreib eine Funktion remove_duplicates(items), die eine neue Liste zurückgibt, in der jedes Element nur einmal vorkommt, dort, wo es zum ersten Mal stand: remove_duplicates([3, 1, 3, 2, 1]) ergibt [3, 1, 2]. Ohne set und dict.fromkeys.
Bau eine neue Liste auf. Bevor ein Element hineinkommt: Steht es schon darin? Das ist deine Kata contains, und hier darfst du in benutzen.
if item not in result: und dann append.
Schreib eine Funktion removeDuplicates(items), die eine neue Liste zurückgibt, in der jedes Element nur einmal vorkommt, dort, wo es zum ersten Mal stand: removeDuplicates([3, 1, 3, 2, 1]) ergibt [3, 1, 2]. Ohne Set.
Bau eine neue Liste auf. Bevor ein Element hineinkommt: Steht es schon darin? Das ist deine Kata contains, und hier darfst du includes benutzen.
if (!result.includes(item)) und dann push.
In der Liste stehen die Zahlen von 1 bis n, durcheinander, und genau eine fehlt. Die Liste hat also n - 1 Zahlen. Schreib eine Funktion missing_number(numbers), die die fehlende Zahl zurückgibt: missing_number([3, 1, 5, 2]) ergibt 4. Geht es ohne zu suchen?
Wie groß ist n? Die Liste hat n - 1 Zahlen.
Du weißt, was alle Zahlen von 1 bis n zusammen ergeben: sum_to(n) aus den Schleifen, oder n · (n + 1) / 2. Was fehlt, wenn du die Zahlen der Liste davon abziehst?
In der Liste stehen die Zahlen von 1 bis n, durcheinander, und genau eine fehlt. Die Liste hat also n - 1 Zahlen. Schreib eine Funktion missing_number(numbers), die die fehlende Zahl zurückgibt: missing_number([3, 1, 5, 2]) ergibt 4. Geht es ohne zu suchen?
Wie groß ist n? Die Liste hat n - 1 Zahlen.
Du weißt, was alle Zahlen von 1 bis n zusammen ergeben: sum_to(n) aus den Schleifen, oder n · (n + 1) / 2. Was fehlt, wenn du die Zahlen der Liste davon abziehst?
In der Liste stehen die Zahlen von 1 bis n, durcheinander, und genau eine fehlt. Die Liste hat also n - 1 Zahlen. Schreib eine Funktion missingNumber(numbers), die die fehlende Zahl zurückgibt: missingNumber([3, 1, 5, 2]) ergibt 4. Geht es ohne zu suchen?
Wie groß ist n? Die Liste hat n - 1 Zahlen.
Du weißt, was alle Zahlen von 1 bis n zusammen ergeben: sumTo(n) aus den Schleifen, oder n · (n + 1) / 2. Was fehlt, wenn du die Zahlen der Liste davon abziehst?
a und b sind aufsteigend sortiert. Schreib eine Funktion merge_sorted(a, b), die daraus eine sortierte Liste macht, ohne zu sortieren: Schau immer auf die vorderste Zahl beider Listen und nimm die kleinere. merge_sorted([1, 4, 6], [2, 3, 7]) ergibt [1, 2, 3, 4, 6, 7].
Zwei Zählvariablen, i für a und j für b, zeigen auf die vorderste Zahl, die noch nicht im Ergebnis ist. Die kleinere von a[i] und b[j] kommt hinein, und ihre Zählvariable rückt weiter.
Das geht, solange beide Listen noch Zahlen haben. Was ist danach mit dem Rest? a[i..] ist alles ab dem Index i.
a und b sind aufsteigend sortiert. Schreib eine Funktion merge_sorted(a, b), die daraus eine sortierte Liste macht, ohne zu sortieren: Schau immer auf die vorderste Zahl beider Listen und nimm die kleinere. merge_sorted([1, 4, 6], [2, 3, 7]) ergibt [1, 2, 3, 4, 6, 7].
Zwei Zählvariablen, i für a und j für b, zeigen auf die vorderste Zahl, die noch nicht im Ergebnis ist. Die kleinere von a[i] und b[j] kommt hinein, und ihre Zählvariable rückt weiter.
Das geht, solange beide Listen noch Zahlen haben. Was ist danach mit dem Rest? a[i:] ist alles ab dem Index i.
a und b sind aufsteigend sortiert. Schreib eine Funktion mergeSorted(a, b), die daraus eine sortierte Liste macht, ohne zu sortieren: Schau immer auf die vorderste Zahl beider Listen und nimm die kleinere. mergeSorted([1, 4, 6], [2, 3, 7]) ergibt [1, 2, 3, 4, 6, 7].
Zwei Zählvariablen, i für a und j für b, zeigen auf die vorderste Zahl, die noch nicht im Ergebnis ist. Die kleinere von a[i] und b[j] kommt hinein, und ihre Zählvariable rückt weiter.
Das geht, solange beide Listen noch Zahlen haben. Was ist danach mit dem Rest? a.slice(i) ist alles ab dem Index i.
Das Mischen zweier sortierter Listen ist der Kern von Merge Sort: Wer eine Liste halbiert, beide Hälften sortiert und sie dann so mischt, hat sie sortiert. Ganze Sortierverfahren schreibst, beobachtest und vergleichst du in der Sorting Sandbox; wie Listen im Speicher aussehen, zeigt die Data Structures Sandbox.
Ein Extra für Schnelle: Die Seite ist ohne dieses Kapitel vollständig.
Zwei Katas, die nicht mitzählen.
Schreib eine Funktion two_sum(numbers, target), die die Indizes der ersten zwei Zahlen zurückgibt, die zusammen target ergeben, als Liste [i, j] mit i < j: two_sum([2, 7, 11, 15], 9) ergibt [0, 1]. »Die ersten« heißt: mit dem kleinsten j, und bei gleichem j mit dem kleinsten i. Gibt es keine, kommt [] zurück.
Zwei Schleifen ineinander: die äußere für j, die innere für alle i vor j.
Mit einem Hash, der sich merkt, welche Zahl an welchem Index stand, geht es mit einer einzigen Schleife. Das kommt bei den Dictionaries.
Schreib eine Funktion two_sum(numbers, target), die die Indizes der ersten zwei Zahlen zurückgibt, die zusammen target ergeben, als Liste [i, j] mit i < j: two_sum([2, 7, 11, 15], 9) ergibt [0, 1]. »Die ersten« heißt: mit dem kleinsten j, und bei gleichem j mit dem kleinsten i. Gibt es keine, kommt [] zurück.
Zwei Schleifen ineinander: die äußere für j, die innere für alle i vor j.
Mit einem Dictionary, das sich merkt, welche Zahl an welchem Index stand, geht es mit einer einzigen Schleife. Das kommt bei den Dictionaries.
Schreib eine Funktion twoSum(numbers, target), die die Indizes der ersten zwei Zahlen zurückgibt, die zusammen target ergeben, als Liste [i, j] mit i < j: twoSum([2, 7, 11, 15], 9) ergibt [0, 1]. »Die ersten« heißt: mit dem kleinsten j, und bei gleichem j mit dem kleinsten i. Gibt es keine, kommt [] zurück.
Zwei Schleifen ineinander: die äußere für j, die innere für alle i vor j.
Mit einer Map, die sich merkt, welche Zahl an welchem Index stand, geht es mit einer einzigen Schleife. Das kommt bei den Dictionaries.
Schreib eine Funktion chunks(items, size), die die Liste in Stücke von je size Elementen teilt; das letzte Stück darf kürzer sein: chunks([1, 2, 3, 4, 5], 2) ergibt [[1, 2], [3, 4], [5]]. Ohne each_slice.
Der Anfang jedes Stücks liegt bei den Indizes 0, size, 2 * size … items[i, size] sind size Elemente ab dem Index i, am Ende auch weniger.
Eine while-Schleife, in der i jedes Mal um size wächst.
Schreib eine Funktion chunks(items, size), die die Liste in Stücke von je size Elementen teilt; das letzte Stück darf kürzer sein: chunks([1, 2, 3, 4, 5], 2) ergibt [[1, 2], [3, 4], [5]].
Der Anfang jedes Stücks liegt bei den Indizes 0, size, 2 * size … items[i:i + size] sind die Elemente ab dem Index i, am Ende auch weniger.
range(0, len(items), size) zählt in Schritten von size.
Schreib eine Funktion chunks(items, size), die die Liste in Stücke von je size Elementen teilt; das letzte Stück darf kürzer sein: chunks([1, 2, 3, 4, 5], 2) ergibt [[1, 2], [3, 4], [5]].
Der Anfang jedes Stücks liegt bei den Indizes 0, size, 2 * size … items.slice(i, i + size) sind die Elemente ab dem Index i, am Ende auch weniger.
Eine Schleife, in der i jedes Mal um size wächst: i += size.