Skip to content
kata / a language workbench

Word frequency

Count words in a fixed sentence after lowercasing it and removing periods. Empty pieces are skipped, and a separate vocabulary array determines the reporting order.

let text = "Small steps. Small programs. Clear steps."
let words = text.to_lower().replace(".", "").split(" ")
let counts = Map[Str, Int].new()
for word in words {
if word == "" { cont }
let previous = counts.get(word).unwrap_or(0)
counts[word] = previous + 1
}
for word in ["small", "steps", "programs", "clear"] {
print("{word}: {counts[word]}")
}
print("distinct words: {counts.len()}")
Original example: checked output and syntax tree

These records belong to the original downloadable program. Run the editor above to see results for your changes.

small: 2
steps: 2
programs: 1
clear: 1
distinct words: 4
Original AST
[
  {
    "node": {
      "Let": {
        "pattern": {
          "node": {
            "Binding": {
              "node": "text",
              "span": [
                4,
                8
              ]
            }
          },
          "span": [
            4,
            8
          ]
        },
        "type_ann": null,
        "value": {
          "node": {
            "Str": "Small steps. Small programs. Clear steps."
          },
          "span": [
            11,
            54
          ]
        }
      }
    },
    "span": [
      0,
      54
    ]
  },
  {
    "node": {
      "Let": {
        "pattern": {
          "node": {
            "Binding": {
              "node": "words",
              "span": [
                59,
                64
              ]
            }
          },
          "span": [
            59,
            64
          ]
        },
        "type_ann": null,
        "value": {
          "node": {
            "Call": {
              "callee": {
                "node": {
                  "Attr": {
                    "object": {
                      "node": {
                        "Call": {
                          "callee": {
                            "node": {
                              "Attr": {
                                "object": {
                                  "node": {
                                    "Call": {
                                      "callee": {
                                        "node": {
                                          "Attr": {
                                            "object": {
                                              "node": {
                                                "Name": "text"
                                              },
                                              "span": [
                                                67,
                                                71
                                              ]
                                            },
                                            "name": "to_lower",
                                            "name_span": [
                                              72,
                                              80
                                            ]
                                          }
                                        },
                                        "span": [
                                          67,
                                          80
                                        ]
                                      },
                                      "args": [],
                                      "args_span": [
                                        80,
                                        82
                                      ]
                                    }
                                  },
                                  "span": [
                                    67,
                                    82
                                  ]
                                },
                                "name": "replace",
                                "name_span": [
                                  83,
                                  90
                                ]
                              }
                            },
                            "span": [
                              67,
                              90
                            ]
                          },
                          "args": [
                            {
                              "node": {
                                "Str": "."
                              },
                              "span": [
                                91,
                                94
                              ]
                            },
                            {
                              "node": {
                                "Str": ""
                              },
                              "span": [
                                96,
                                98
                              ]
                            }
                          ],
                          "args_span": [
                            90,
                            99
                          ]
                        }
                      },
                      "span": [
                        67,
                        99
                      ]
                    },
                    "name": "split",
                    "name_span": [
                      100,
                      105
                    ]
                  }
                },
                "span": [
                  67,
                  105
                ]
              },
              "args": [
                {
                  "node": {
                    "Str": " "
                  },
                  "span": [
                    106,
                    109
                  ]
                }
              ],
              "args_span": [
                105,
                110
              ]
            }
          },
          "span": [
            67,
            110
          ]
        }
      }
    },
    "span": [
      55,
      110
    ]
  },
  {
    "node": {
      "Let": {
        "pattern": {
          "node": {
            "Binding": {
              "node": "counts",
              "span": [
                115,
                121
              ]
            }
          },
          "span": [
            115,
            121
          ]
        },
        "type_ann": null,
        "value": {
          "node": {
            "Call": {
              "callee": {
                "node": {
                  "Attr": {
                    "object": {
                      "node": {
                        "Item": {
                          "object": {
                            "node": {
                              "Name": "Map"
                            },
                            "span": [
                              124,
                              127
                            ]
                          },
                          "args": [
                            {
                              "node": {
                                "Name": "Str"
                              },
                              "span": [
                                128,
                                131
                              ]
                            },
                            {
                              "node": {
                                "Name": "Int"
                              },
                              "span": [
                                133,
                                136
                              ]
                            }
                          ]
                        }
                      },
                      "span": [
                        124,
                        137
                      ]
                    },
                    "name": "new",
                    "name_span": [
                      138,
                      141
                    ]
                  }
                },
                "span": [
                  124,
                  141
                ]
              },
              "args": [],
              "args_span": [
                141,
                143
              ]
            }
          },
          "span": [
            124,
            143
          ]
        }
      }
    },
    "span": [
      111,
      143
    ]
  },
  {
    "node": {
      "Expr": {
        "node": {
          "For": {
            "pattern": {
              "node": {
                "Binding": {
                  "node": "word",
                  "span": [
                    148,
                    152
                  ]
                }
              },
              "span": [
                148,
                152
              ]
            },
            "iter_expr": {
              "node": {
                "Name": "words"
              },
              "span": [
                156,
                161
              ]
            },
            "body": [
              {
                "node": {
                  "Expr": {
                    "node": {
                      "If": {
                        "cond": {
                          "node": {
                            "BinOp": {
                              "op": "Eq",
                              "left": {
                                "node": {
                                  "Name": "word"
                                },
                                "span": [
                                  171,
                                  175
                                ]
                              },
                              "right": {
                                "node": {
                                  "Str": ""
                                },
                                "span": [
                                  179,
                                  181
                                ]
                              }
                            }
                          },
                          "span": [
                            171,
                            181
                          ]
                        },
                        "then_body": [
                          {
                            "node": {
                              "Cont": {
                                "keyword": [
                                  184,
                                  188
                                ]
                              }
                            },
                            "span": [
                              184,
                              188
                            ]
                          }
                        ],
                        "else_body": null
                      }
                    },
                    "span": [
                      168,
                      190
                    ]
                  }
                },
                "span": [
                  168,
                  190
                ]
              },
              {
                "node": {
                  "Let": {
                    "pattern": {
                      "node": {
                        "Binding": {
                          "node": "previous",
                          "span": [
                            199,
                            207
                          ]
                        }
                      },
                      "span": [
                        199,
                        207
                      ]
                    },
                    "type_ann": null,
                    "value": {
                      "node": {
                        "Call": {
                          "callee": {
                            "node": {
                              "Attr": {
                                "object": {
                                  "node": {
                                    "Call": {
                                      "callee": {
                                        "node": {
                                          "Attr": {
                                            "object": {
                                              "node": {
                                                "Name": "counts"
                                              },
                                              "span": [
                                                210,
                                                216
                                              ]
                                            },
                                            "name": "get",
                                            "name_span": [
                                              217,
                                              220
                                            ]
                                          }
                                        },
                                        "span": [
                                          210,
                                          220
                                        ]
                                      },
                                      "args": [
                                        {
                                          "node": {
                                            "Name": "word"
                                          },
                                          "span": [
                                            221,
                                            225
                                          ]
                                        }
                                      ],
                                      "args_span": [
                                        220,
                                        226
                                      ]
                                    }
                                  },
                                  "span": [
                                    210,
                                    226
                                  ]
                                },
                                "name": "unwrap_or",
                                "name_span": [
                                  227,
                                  236
                                ]
                              }
                            },
                            "span": [
                              210,
                              236
                            ]
                          },
                          "args": [
                            {
                              "node": {
                                "Int": "0"
                              },
                              "span": [
                                237,
                                238
                              ]
                            }
                          ],
                          "args_span": [
                            236,
                            239
                          ]
                        }
                      },
                      "span": [
                        210,
                        239
                      ]
                    }
                  }
                },
                "span": [
                  195,
                  239
                ]
              },
              {
                "node": {
                  "Assign": {
                    "target": {
                      "Item": {
                        "object": {
                          "node": {
                            "Name": "counts"
                          },
                          "span": [
                            244,
                            250
                          ]
                        },
                        "args": [
                          {
                            "node": {
                              "Name": "word"
                            },
                            "span": [
                              251,
                              255
                            ]
                          }
                        ]
                      }
                    },
                    "value": {
                      "node": {
                        "BinOp": {
                          "op": "Add",
                          "left": {
                            "node": {
                              "Name": "previous"
                            },
                            "span": [
                              259,
                              267
                            ]
                          },
                          "right": {
                            "node": {
                              "Int": "1"
                            },
                            "span": [
                              270,
                              271
                            ]
                          }
                        }
                      },
                      "span": [
                        259,
                        271
                      ]
                    }
                  }
                },
                "span": [
                  244,
                  271
                ]
              }
            ]
          }
        },
        "span": [
          144,
          273
        ]
      }
    },
    "span": [
      144,
      273
    ]
  },
  {
    "node": {
      "Expr": {
        "node": {
          "For": {
            "pattern": {
              "node": {
                "Binding": {
                  "node": "word",
                  "span": [
                    278,
                    282
                  ]
                }
              },
              "span": [
                278,
                282
              ]
            },
            "iter_expr": {
              "node": {
                "ArrLit": {
                  "elements": [
                    {
                      "node": {
                        "Str": "small"
                      },
                      "span": [
                        287,
                        294
                      ]
                    },
                    {
                      "node": {
                        "Str": "steps"
                      },
                      "span": [
                        296,
                        303
                      ]
                    },
                    {
                      "node": {
                        "Str": "programs"
                      },
                      "span": [
                        305,
                        315
                      ]
                    },
                    {
                      "node": {
                        "Str": "clear"
                      },
                      "span": [
                        317,
                        324
                      ]
                    }
                  ]
                }
              },
              "span": [
                286,
                325
              ]
            },
            "body": [
              {
                "node": {
                  "Expr": {
                    "node": {
                      "Call": {
                        "callee": {
                          "node": {
                            "Name": "print"
                          },
                          "span": [
                            332,
                            337
                          ]
                        },
                        "args": [
                          {
                            "node": {
                              "Interp": {
                                "parts": [
                                  {
                                    "Expr": {
                                      "node": {
                                        "Name": "word"
                                      },
                                      "span": [
                                        340,
                                        344
                                      ]
                                    }
                                  },
                                  {
                                    "Lit": ": "
                                  },
                                  {
                                    "Expr": {
                                      "node": {
                                        "Item": {
                                          "object": {
                                            "node": {
                                              "Name": "counts"
                                            },
                                            "span": [
                                              348,
                                              354
                                            ]
                                          },
                                          "args": [
                                            {
                                              "node": {
                                                "Name": "word"
                                              },
                                              "span": [
                                                355,
                                                359
                                              ]
                                            }
                                          ]
                                        }
                                      },
                                      "span": [
                                        348,
                                        360
                                      ]
                                    }
                                  }
                                ]
                              }
                            },
                            "span": [
                              338,
                              362
                            ]
                          }
                        ],
                        "args_span": [
                          337,
                          363
                        ]
                      }
                    },
                    "span": [
                      332,
                      363
                    ]
                  }
                },
                "span": [
                  332,
                  363
                ]
              }
            ]
          }
        },
        "span": [
          274,
          365
        ]
      }
    },
    "span": [
      274,
      365
    ]
  },
  {
    "node": {
      "Expr": {
        "node": {
          "Call": {
            "callee": {
              "node": {
                "Name": "print"
              },
              "span": [
                366,
                371
              ]
            },
            "args": [
              {
                "node": {
                  "Interp": {
                    "parts": [
                      {
                        "Lit": "distinct words: "
                      },
                      {
                        "Expr": {
                          "node": {
                            "Call": {
                              "callee": {
                                "node": {
                                  "Attr": {
                                    "object": {
                                      "node": {
                                        "Name": "counts"
                                      },
                                      "span": [
                                        390,
                                        396
                                      ]
                                    },
                                    "name": "len",
                                    "name_span": [
                                      397,
                                      400
                                    ]
                                  }
                                },
                                "span": [
                                  390,
                                  400
                                ]
                              },
                              "args": [],
                              "args_span": [
                                400,
                                402
                              ]
                            }
                          },
                          "span": [
                            390,
                            402
                          ]
                        }
                      }
                    ]
                  }
                },
                "span": [
                  372,
                  404
                ]
              }
            ],
            "args_span": [
              371,
              405
            ]
          }
        },
        "span": [
          366,
          405
        ]
      }
    },
    "span": [
      366,
      405
    ]
  }
]
Download original word-frequency.ks ↓

On a word’s first occurrence, the map has no entry. get(word) returns Opt[Int], and unwrap_or(0) supplies the missing count. Updating the map then uses the same expression for both new and repeated words.

The final reporting loop uses indexing because every listed word is known to occur. For an unknown report vocabulary, use get there too.

This is a deliberately small tokenizer: it only normalizes periods, case, and spaces. It neither sorts words nor handles general punctuation.

Read the full tutorial to build the program one decision at a time, or consult the collection APIs.