DEV Community

Discussion on: Daily Challenge #282 - Car License Plate Calculator

Collapse
 
n8chz profile image
Lorraine Lee • Edited
find_plate(CustomerId, NumberPlate) :-
  var(NumberPlate),
  divmod(CustomerId, 1000, Q1, R1),
  divmod(Q1, 26, Q2, R2),
  divmod(Q2, 26, R4, R3),
  R1Plus is R1 + 1000,
  atom_chars(R1Plus, [_ | Digits]),
  C2 is R2+97,
  C3 is R3+97,
  C4 is R4+97,
  atom_chars(Letters, [C4, C3, C2]),
  atomic_list_concat([Letters | Digits], NumberPlate), !.

find_plate(CustomerId, NumberPlate) :-
  atom_codes(NumberPlate, [L1, L2, L3, N1, N2, N3]),
  atom_codes(NA, [N1, N2, N3]),
  atom_number(NA, N),
  CustomerId is 676000*(L1-97)+26000*(L2-97)+1000*(L3-97)+N.
Collapse
 
n8chz profile image
Lorraine Lee • Edited

I thought to use Elixir since it has built-in base conversion (and not just for the usual powers of two suspects like octal and hex), but theirs assumes the digit sequence is 0..9A..Z, so there is still an impedance mismatch to a..z encoding, and the need (apparently) to bludgeon one's way through the edge cases, particularly 'magic constants' based on knowledge of the ASCII character set.

defmodule FindPlate do
  @doc """
  Generate a number plate from a customer_id
  """
  @spec find_plate(Integer.t()) :: String.t()
  def find_plate(customer_id) do
    {mst, digits} = (customer_id+26*26*26*1000) # kludge
    |> Integer.to_charlist
    |> Enum.split(-3)
    mst = if(mst == [], do: '0', else: mst) # kludge
    {_, letters} = mst
    |> List.to_integer
    |> Integer.to_charlist(26)
    |> Enum.map(fn c -> if(c <= ?9, do: c+?a-?0, else: c+42) end)
    |> Enum.split(-3) # counterkludge
    letters++digits
  end
end