2

I found code to generate n distinct colors. I took the code and made a class out of it

import colorsys
import itertools
from fractions import Fraction

class DistinctColorsGenerator:
    def __init__(self):
        self._bias = lambda x: (math.sqrt(x / 3) / Fraction(2, 3) + Fraction(1, 3)) / Fraction(6, 5)
        self._gen_rgb = lambda x : colorsys.hsv_to_rgb(*x)
        self._flatten = itertools.chain.from_iterable
        self._hsvs = lambda: self._flatten(map(self._hsv, self._fracs()))
        self._rgbs = lambda: map(self._gen_rgb, self._hsvs())
        self._gen_colors = lambda: map(self._gen_color, self._rgbs())

    def generate(self, number):
        return list(itertools.islice(self._gen_colors(), number))

    def _zenos_dichotomy(self):
        for k in itertools.count():
            yield Fraction(1, 2 ** k)

    def _fracs(self):
        yield 0
        for k in self._zenos_dichotomy():
            i = k.denominator
            for j in range(1, i, 2):
                yield Fraction(j, i)

    def _hsv(self, h):
        for s in [Fraction(6, 10)]:
            for v in [Fraction(8, 10), Fraction(5, 10)]:
                yield (h, s, v)

    def _gen_color(self, x):
        uint8tuple = map(lambda y: int(y * 255), x)
        return list(uint8tuple)

I want to convert this to Kotlin, and the problem is that most of my Kotlin experience (as well as Python) is writing ordinary boring code. Whereas it looks like this one solves the problem by generating an infinite sequence and evaluating it lazily. I can just look at the Python code, understand what is going on and write a simple and boring code. But before doing that I wanted to ask here whether someone could show how a similar thing can be implemented in Kotlin

1
  • 2
    Kotlin supports coroutines, which serve the exact same purpose as Python's generators (i.e. "lazily evaluated possibly infinite sequences"). So it would absolutely be possible to translate this code. Commented Oct 26, 2017 at 16:28

1 Answer 1

5

I read some documentation (as was suggested in the comments) and this is what I came up with (just in case someone will find that useful)

class DistinctColorsGenerator {
    fun generate(number: Int): List<ColorRgb> = generateRgbs.take(number).toList()

    private val genHsvs = buildSequence {
        fractions.forEach { createHsvColors(it).forEach { yield(it) } }
    }

    private val generateRgbs = buildSequence {
        genHsvs.forEach { yield(it.toRgb()) }
    }

    private val zenosDichotomy = buildSequence {
        var d = 1
        while (true) {
            yield(Fraction(1, d))
            d *= 2
        }
    }

    private val fractions = buildSequence {
        yield(Fraction(0, 1))
        zenosDichotomy.forEach {
            val i = it.denominator.toInt()
            for (j in 1 until i step 2) {
                yield(Fraction(j, i))
            }
        }
    }

    private fun createHsvColors(h: Fraction<Int>) = buildSequence {
        listOf(Fraction(6, 10)).forEach { s ->
            listOf(Fraction(8, 10), Fraction(5, 10)).forEach { v ->
                yield(ColorHsv(h, s, v))
            }
        }
    }
}

Classes ColorRgb, ColorHsv, Fraction are just data classes. ColorHsv.toRgb() I took from here

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.