Inhalt
Die Fakten:
Plattform: | codewars.com |
Name: | IP Address to Number |
Level: | 6 kyu |
Sprache: | TypeScript |
Beschreibung:
An IPv4 address is a 32-bit number that identifies a device on the internet.
While computers read and write IP addresses as a 32-bit number, we prefer to read them in dotted-decimal notation, which is basically the number split into 4 chunks of 8 bits, converted to decimal, and delmited by a dot.
In this kata, you will create the function ipToNum
(or ip_to_num
, depending on the language) that takes an ip
address and converts it to a number, as well as the function numToIp
(or num_to_ip
) that takes a number and converts it to an IP address string. Input will always be valid.
Conversion Example
//original IP address
192.168.1.1
//breaks down into 4 binary octets
11000000 . 10101000 . 00000001 . 00000001
//which are merged together (unsigned 32-bit binary)
11000000101010000000000100000001
//and finally converted to base 10
3232235777
Note that the binary octets are unsigned (so we can't have negative numbers).
Be careful: JavaScript does bitwise arithmetic on *signed* 32-bits integers.
Examples
ipToNum / ip_to_num
'192.168.1.1' converts to 3232235777
'10.0.0.0' converts to 167772160
'176.16.0.1' converts to 2953838593
numToIp / num_to_ip
3232235777 converts to '192.168.1.1'
167772160 converts to '10.0.0.0'
2953838593 converts to '176.16.0.1'
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
Als Erstes die Funktion ipToNum()
Schritt 1
Wir entfernen die Punkte und wandeln den String in ein Array um.
Schritt 2
Dann loopen wir durch das Array und wandeln jedes Element in seine 8-stellige Binär-Version um.
Schritt 3
Jetzt können wir die Elemente wieder zu einem String zusammenführen und diesen 32-Bit-Binär-String dann in einen Integer umwandeln.
Dann die Funktion numToIP()
Schritt 4
Zuerst wandeln wir die Input-Zahl in eine 32-stellige Binär-Zahl um.
Schritt 5
Dann teilen wir diese in 4 Teile bzw. Bytes à 8 Zeichen bzw. Bits.
Schritt 6
Diese 4 Bytes wandeln wir dann jeweils in ein Integer um.
Schritt 7
Am Ende wandeln wir das Array in einen String mit einem Punkt als Trennzeichen.
Code
Geil. Übersetzen wir unseren Pseudo-Code in TypeScript:
Lösungsschritte
Die erste Zeile meiner ipToNum()
-Funktion:
export function ipToNum(ip: string): number {
Als Erstes machen wir aus dem String die 8-stellige Binär-Version ohne Punkte:
const binary32bit = ip
.split(".")
.map(Number)
.map((num) => num.toString(2).padStart(8, "0"))
.join("");
Das geht hier wunderbar mit Method-Chaining.
.map(Number)
loopt hier ein Mal durch alle Elemente und wandelt die String-Zahlen in richtige Zahlen um.
.toString(2)
macht aus einer Zahl ihre Binär-Version.
Mit .padStart(8, “0”)
sorgen wir dafür, dass wir immer eine 8-stelliege Binärzahl bzw. ein Byte erhalten.
Und mit .join()
fügen wir alle 4 Bytes zu einer 32-stelligen Zahl zusammen.
Nur noch in einen Integer konvertieren und zurückgeben:
return parseInt(binary32bit, 2);
}
Das war sie schon, die ipToNum()
-Funktion. Weiter geht’s mit der numToIp()
-Funktion.
Die erste Zeile meiner numToIp()
-Funktion:
export function numToIp(num: number): string {
Input-Zahl in eine 32-stellige Binärzahl umwandeln:
const binary32bit = num.toString(2).padStart(32, "0");
Um sicherzustellen, dass wir 32-Bits bekommen, fügen wir mit .padStart(32, "0")
wieder eventuell noch fehlende Nullen hinzu.
Dann die Binärzahl in 4 Teile/Bytes á 8 Bits teilen:
const bytes = ["", "", "", ""].map((_, i) => {
const byteStart = i * 8;
const byteEnd = (i + 1) * 8;
return binary32bit.slice(byteStart, byteEnd);
});
Jetzt die Bytes in Integer umwandeln:
const nums = bytes.map((byte) => parseInt(byte, 2));
Zum Schluss das Ganze in einen String mit Punkten konvertieren und zurückgeben:
return nums.join(".");
}
Voilá! 💪
Komplettlösung
export function ipToNum(ip: string): number {
const binary32bit = ip
.split(".")
.map(Number)
.map((num) => num.toString(2).padStart(8, "0"))
.join("");
return parseInt(binary32bit, 2);
}
export function numToIp(num: number): string {
const binary32bit = num.toString(2).padStart(32, "0");
const bytes = ["", "", "", ""].map((_, i) => {
const byteStart = i * 8;
const byteEnd = (i + 1) * 8;
return binary32bit.slice(byteStart, byteEnd);
});
const nums = bytes.map((byte) => parseInt(byte, 2));
return nums.join(".");
}