The Big Book of Small EK9 Programs

Adapted from Al Sweigart's The Big Book of Small Python Projects: 81 Easy Practice Programs (No Starch Press, 2021; copyright © 2021 Al Sweigart), which he makes freely available under a Creative Commons Attribution-NonCommercial-ShareAlike licence at inventwithpython.com/bigbookpython. Changes were made: each program was ported from Python to EK9 and remodelled in EK9's idioms.

Project 64 — Seven-Segment Display Module

This is project 64 of the book, ported to EK9. Its chapter is still being written; until then, this page shows the port itself: a run of it, the whole program, and how it keeps to the original.

A sample run

Run it with:

ek9 sevensegment.ek9 1234567890 12

It prints:

 __   __        __   __        __   __   __   __   __   __ 
|  | |  |    |  __|  __| |__| |__  |__     | |__| |__| |  |
|__| |__|    | |__   __|    |  __| |__|    | |__|  __| |__|

The program

#!ek9
defines module bigbook.sevensegment

  defines type

    List of Shape

  defines record

    //One numeral drawn as three rows, top to bottom. A record keeps a numeral's rows together,
    //where three separate tables keyed by the same numerals could drift apart.
    Shape
      top as String: String()
      middle as String: String()
      bottom as String: String()

      default Shape() as pure

      Shape() as pure
        ->
          topRow as String
          middleRow as String
          bottomRow as String

        top :=? String(topRow)
        middle :=? String(middleRow)
        bottom :=? String(bottomRow)

      default operator ?

  defines class

    //THE OUTPUT: everything the reader sees goes through here. The display has no words, so
    //there is no Say, and the number is a program argument, so there is no LineInput.
    Console
      stdout as Stdout: Stdout()

      //The numerals are computed: they are shown as the game drew them, a row at a time.
      showRows()
        -> rows as List of String
        for row in rows
          stdout.println(row)

      override operator ? as pure
        <- rtn as Boolean: true

  defines function

    //THE GAME: the numerals, as rows, with no output.

    //The book's table of shapes: data, every shape four characters wide. An Integer's text
    //holds only digits and a minus sign.
    numeralShapes() as pure
      <- rtn as Dict of (Character, Shape): {
        '0': Shape(" __ ", "|  |", "|__|"),
        '1': Shape("    ", "   |", "   |"),
        '2': Shape(" __ ", " __|", "|__ "),
        '3': Shape(" __ ", " __|", " __|"),
        '4': Shape("    ", "|__|", "   |"),
        '5': Shape(" __ ", "|__ ", " __|"),
        '6': Shape(" __ ", "|__ ", "|__|"),
        '7': Shape(" __ ", "   |", "   |"),
        '8': Shape(" __ ", "|__|", "|__|"),
        '9': Shape(" __ ", "|__|", " __|"),
        '-': Shape("    ", " __ ", "    ")
      }

    shapeOf() as pure
      -> numeral as Character
      <- rtn as Shape: Shape()
      shapes <- numeralShapes()
      rtn: shapes.getOrDefault(numeral, Shape())

    topOf() as pure
      -> shape as Shape
      <- rtn as String: shape.top

    middleOf() as pure
      -> shape as Shape
      <- rtn as String: shape.middle

    bottomOf() as pure
      -> shape as Shape
      <- rtn as String: shape.bottom

    //The book puts one space between neighbouring numerals.
    spaced() as pure
      ->
        left as String
        right as String
      <- rtn as String: `${left} ${right}`

    //The book's getSevSegStr: the number zero-padded to at least minimumWidth digits, drawn as
    //three rows. The book joins the rows with newlines; a List of rows leaves that to the caller.
    sevenSegmentRows() as pure
      ->
        number as Integer
        minimumWidth as Integer
      <- rtn as List of String: List() of String

      digits <- $number
      shapes <- cat digits.zeroPad(minimumWidth) | map with shapeOf | collect as List of Shape
      topRow <- cat shapes | map with topOf | join with spaced | collect as String
      middleRow <- cat shapes | map with middleOf | join with spaced | collect as String
      bottomRow <- cat shapes | map with bottomOf | join with spaced | collect as String
      rtn: [topRow, middleRow, bottomRow]

  defines program

    //Sevseg (Big Book project 64). Draws the number it is given as seven-segment display digits.
    //The game decides; the Console shows it.
    SevenSegment()
      ->
        number as Integer
        minimumWidth as Integer

      console <- Console()

      console.showRows(sevenSegmentRows(number, minimumWidth))

About this port