Python Challenge - Level 5

Problem

pronounce it

Page source contains:

<peakhell src="banner.p" />
<!-- peak hell sounds familiar ? -->

peakhell → sounds like → pickle — Python's binary serialization format.

Solution

The file banner.p is a pickled Python object. It's a list of lists of (char, count) tuples — a run-length encoded banner.

Python

import urllib.request, pickle

data = pickle.load(urllib.request.urlopen(
    "http://www.pythonchallenge.com/pc/def/banner.p"
))

for line in data:
    print("".join(char * count for char, count in line))

Output (ASCII art):

              #####                                       #####
   ###   ##   #### #######    ##  ###   #### #######   ###  ###  ####
  ###     ###  #####    ####  ###  ####  #####    #### ###     ### ####
  ...

The banner reads: channel

Go

Python's pickle format is Python-specific — Go has no standard library support. The practical approach is to avoid re-implementing pickle and instead run a Python helper to decode + re-encode as JSON, then consume JSON in Go:

// Step 1 (Python helper): convert banner.p → banner.json
// import pickle, json, urllib.request
// data = pickle.load(urllib.request.urlopen("...banner.p"))
// print(json.dumps(data))

// Step 2 (Go): decode JSON and render
package main

import (
    "encoding/json"
    "fmt"
    "os/exec"
    "strings"
)

func main() {
    out, _ := exec.Command("python3", "-c", `
import pickle, json, urllib.request
data = pickle.load(urllib.request.urlopen(
    "http://www.pythonchallenge.com/pc/def/banner.p"))
print(json.dumps(data))
`).Output()

    var lines [][][]interface{}
    json.Unmarshal(out, &lines)

    for _, line := range lines {
        var sb strings.Builder
        for _, pair := range line {
            char := pair[0].(string)
            count := int(pair[1].(float64))
            sb.WriteString(strings.Repeat(char, count))
        }
        fmt.Println(sb.String())
    }
}

Rust

Same approach — use the pickle crate or delegate to Python:

// Using the `serde-pickle` crate (add to Cargo.toml:
//   serde-pickle = "1.1"
//   reqwest = { version = "0.11", features = ["blocking"] }

use serde_pickle::Value;
use reqwest::blocking::get;

fn main() {
    let bytes = get("http://www.pythonchallenge.com/pc/def/banner.p")
        .unwrap().bytes().unwrap();

    let data: Value = serde_pickle::from_slice(&bytes, Default::default()).unwrap();

    if let Value::List(lines) = data {
        for line in lines {
            if let Value::List(pairs) = line {
                let row: String = pairs.iter().filter_map(|pair| {
                    if let Value::Tuple(items) = pair {
                        let ch = match &items[0] {
                            Value::String(s) => s.chars().next().unwrap(),
                            _ => return None,
                        };
                        let count = match &items[1] {
                            Value::I64(n) => *n as usize,
                            _ => return None,
                        };
                        Some(ch.to_string().repeat(count))
                    } else { None }
                }).collect();
                println!("{}", row);
            }
        }
    }
}

Language Comparison

Feature Python Go Rust
Pickle support pickle — built-in stdlib ❌ None — external bridge required serde-pickle crate (community)
Run-length decoding char * count — string repetition operator strings.Repeat(char, count) ch.to_string().repeat(count)
Binary format portability Python-native only Not portable — use JSON/protobuf/msgpack instead serde-pickle crate works but is niche
String repetition "x" * 5 → "xxxxx" strings.Repeat("x", 5) "x".repeat(5)

Key insight: pickle is a uniquely Python construct — it serializes live Python objects including arbitrary class instances. Go and Rust have no equivalent because they don't share Python's object model. For cross-language serialization, use JSON, MessagePack, or Protocol Buffers. This puzzle is a reminder that pickle should never be used for data exchange outside of trusted Python-to-Python pipelines.

pickle is also a security risk — never unpickle untrusted data, as it can execute arbitrary code on load.

Next Level

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

Loading...