defmodule PaintByNumberTest do use ExUnit.Case describe "palette_bit_size/1" do @tag task_id: 1 test "needs 1 bit to encode two colors" do color_count = 2 assert PaintByNumber.palette_bit_size(color_count) == 1 end @tag task_id: 1 test "needs 2 bits to encode three colors" do color_count = 3 assert PaintByNumber.palette_bit_size(color_count) == 2 end @tag task_id: 1 test "needs 2 bits to encode four colors" do color_count = 4 assert PaintByNumber.palette_bit_size(color_count) == 2 end @tag task_id: 1 test "needs 3 bits to encode seven colors" do color_count = 7 assert PaintByNumber.palette_bit_size(color_count) == 3 end @tag task_id: 1 test "needs 3 bits to encode eight colors" do color_count = 8 assert PaintByNumber.palette_bit_size(color_count) == 3 end @tag task_id: 1 test "needs 4 bits to encode nine colors" do color_count = 9 assert PaintByNumber.palette_bit_size(color_count) == 4 end @tag task_id: 1 test "needs 4 bits to encode fourteen colors" do color_count = 14 assert PaintByNumber.palette_bit_size(color_count) == 4 end @tag task_id: 1 test "needs 6 bits to encode fifty colors" do color_count = 50 assert PaintByNumber.palette_bit_size(color_count) == 6 end @tag task_id: 1 test "needs 20 bits to encode 1 million colors" do color_count = 1_000_000 assert PaintByNumber.palette_bit_size(color_count) == 20 end end describe "empty_picture/0" do @tag task_id: 2 test "returns an empty bitstring" do assert PaintByNumber.empty_picture() == <<>> end end describe "test_picture/0" do @tag task_id: 3 test "returns the numbers 0, 1, 2, and 3 as fragments of size 2" do assert PaintByNumber.test_picture() == <<0::2, 1::2, 2::2, 3::2>> end end describe "prepend_pixel/3" do @tag task_id: 4 test "works with an empty picture" do picture = <<>> color_count = 16 pixel_color_index = 1 assert PaintByNumber.prepend_pixel(picture, color_count, pixel_color_index) == <<1::4>> end @tag task_id: 4 test "works with a non-empty picture" do picture = <<3::3, 2::3, 2::3>> color_count = 7 pixel_color_index = 0 assert PaintByNumber.prepend_pixel(picture, color_count, pixel_color_index) == <<0::3, 3::3, 2::3, 2::3>> end @tag task_id: 4 test "pixel color overflows if it doesn't fit in palette size" do picture = <<3::6>> color_count = 64 pixel_color_index = 64 assert PaintByNumber.prepend_pixel(picture, color_count, pixel_color_index) == <<0::6, 3::6>> end end describe "get_first_pixel/2" do @tag task_id: 5 test "returns nil if empty picture" do picture = <<>> color_count = 16 assert PaintByNumber.get_first_pixel(picture, color_count) == nil end @tag task_id: 5 test "works with a non-empty picture" do picture = <<1::2, 0::2, 0::2, 2::2>> color_count = 3 assert PaintByNumber.get_first_pixel(picture, color_count) == 1 end @tag task_id: 5 test "can reinterpret picture data with a different color count" do picture = <<0b01::2, 0b10::2, 0b00::2, 0b10::2>> # Color count of 8 means 3 bits. color_count = 8 # We take bits from segments until we have 3 bits. # First, we take `01` from the first segment. Then, `1` from the second segment. # This gives us the binary number `011`, which is equal to the decimal number 5. assert PaintByNumber.get_first_pixel(picture, color_count) == 0b011 end end describe "drop_first_pixel/2" do @tag task_id: 6 test "returns empty picture if empty picture" do picture = <<>> color_count = 5 assert PaintByNumber.drop_first_pixel(picture, color_count) == <<>> end @tag task_id: 6 test "works with a non-empty picture" do picture = <<23::5, 21::5, 15::5, 3::5>> color_count = 32 assert PaintByNumber.drop_first_pixel(picture, color_count) == <<21::5, 15::5, 3::5>> end @tag task_id: 6 test "can reinterpret picture data with a different color count" do picture = <<0b011011::6, 0b110001::6>> # Color count of 4 means 2 bits. color_count = 4 # We remove the first 2 bits from the first segment. assert PaintByNumber.drop_first_pixel(picture, color_count) == <<0b1011::4, 0b110001::6>> end end describe "concat_pictures/2" do @tag task_id: 7 test "two empty pictures result in an empty picture" do picture1 = <<>> picture2 = <<>> assert PaintByNumber.concat_pictures(picture1, picture2) == <<>> end @tag task_id: 7 test "a non-picture with an empty picture" do picture1 = <<5::3, 2::3, 2::3, 4::3>> picture2 = <<>> assert PaintByNumber.concat_pictures(picture1, picture2) == picture1 end @tag task_id: 7 test "an empty picture with a non-empty picture" do picture1 = <<>> picture2 = <<13::4, 11::4, 0::4>> assert PaintByNumber.concat_pictures(picture1, picture2) == picture2 end @tag task_id: 7 test "two non-empty pictures" do picture1 = <<2::4, 2::4, 1::4, 14::4>> picture2 = <<15::4, 14::4>> assert PaintByNumber.concat_pictures(picture1, picture2) == <<2::4, 2::4, 1::4, 14::4, 15::4, 14::4>> end @tag task_id: 7 test "two non-empty pictures with different palette bit sizes" do picture1 = <<0b00::2, 0b01::2, 0b11::2, 0b01::2>> picture2 = <<0b10101::5, 0b10011::5>> assert PaintByNumber.concat_pictures(picture1, picture2) == <<0b00011101::8, 0b10101100::8, 0b11::2>> end end end