Python Challenge - Level 4

Problem

Clicking the image takes you to:

http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=12345

The page responds with:

and the next nothing is 44827

Follow the chain: update the URL with the new number and keep going. The chain eventually terminates with the answer. Two tricky branches you'll hit along the way:

  • "Yes. Divide by two and keep going." → divide the current number by 2
  • The chain loops back to the beginning — you need to detect termination

Solution

Python

import urllib.request, re

url = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s"
num = "12345"
pattern = re.compile(r"and the next nothing is (\d+)")

while True:
    content = urllib.request.urlopen(url % num).read().decode()
    print(content)
    if "divide" in content.lower():
        num = str(int(num) // 2)
        continue
    match = pattern.search(content)
    if not match:
        break
    num = match.group(1)

Result: peak.html

Go

package main

import (
    "fmt"
    "io"
    "net/http"
    "regexp"
    "strconv"
    "strings"
)

func main() {
    urlFmt := "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing=%s"
    num := "12345"
    re := regexp.MustCompile(`and the next nothing is (\d+)`)

    for {
        resp, _ := http.Get(fmt.Sprintf(urlFmt, num))
        body, _ := io.ReadAll(resp.Body)
        resp.Body.Close()
        content := string(body)
        fmt.Println(content)

        if strings.Contains(strings.ToLower(content), "divide") {
            n, _ := strconv.Atoi(num)
            num = strconv.Itoa(n / 2)
            continue
        }
        m := re.FindStringSubmatch(content)
        if m == nil {
            break
        }
        num = m[1]
    }
}

Rust

use reqwest::blocking::get;
use regex::Regex;

fn main() {
    let url_fmt = "http://www.pythonchallenge.com/pc/def/linkedlist.php?nothing={}";
    let mut num = "12345".to_string();
    let re = Regex::new(r"and the next nothing is (\d+)").unwrap();

    loop {
        let url = url_fmt.replace("{}", &num);
        let content = get(&url).unwrap().text().unwrap();
        println!("{}", content);

        if content.to_lowercase().contains("divide") {
            let n: u64 = num.parse().unwrap();
            num = (n / 2).to_string();
            continue;
        }
        match re.captures(&content) {
            Some(caps) => num = caps[1].to_string(),
            None => break,
        }
    }
}

Language Comparison

Feature Python Go Rust
HTTP GET urllib.request.urlopen() — stdlib, synchronous net/http.Get() — stdlib, synchronous reqwest::blocking::get() — external crate
String formatting in URL %s / .format() fmt.Sprintf str::replace or format! macro
Integer division // operator / on integers (truncates) / on integers (truncates)
Regex capture group .group(1) FindStringSubmatch()[1] caps[1] or .get(1)
Loop control continue / break continue / break continue / break

Key insight: This puzzle is a linked list traversal over HTTP — the stateful loop pattern is essentially the same in all three languages. The biggest ergonomic gap is HTTP: Python's urllib is clunky but stdlib; Go's net/http is production-grade and stdlib; Rust needs reqwest (external, async by default — use the blocking feature for simplicity).

Next Level

http://www.pythonchallenge.com/pc/def/peak.html