14 задач по Kotlin lists, которые заставят вас подумать

d1e1eecd5a51bfba6643c140735b8cb7.png

Привет, Хабр! Меня зовут Леонид Иванькин, я ведущий Android-разработчик в МТС Digital, работаю над приложением Мой МТС. В этой статье — сложные и не очень задачи, чтобы проверить, насколько хорошо вы разбираетесь в операторах для списков. Готовы испытать свои скиллы? Тогда переходите под кат!

При разработке на Kotlin часто приходится использовать списки (List, MutableList и другие), а также операторы для них. Каждый раз, заходя в документацию, я убеждаюсь, что операторов очень много, а в их использовании есть тонкости.

Многие коллеги говорят, что в этой теме они разбираются на 100%. Давайте проверим, насколько хорошо вы владеете операторами для списков. Я подготовил 14 логических задач разной сложности, попробуйте их решить.

Ставлю на то, что даже опытные разработчики справятся не со всеми задачами, несмотря на кажущуюся простоту :)

Правила

Есть задание — лист элементов. Ваша задача вставить один оператор, чтобы получилось значение в комментариях, которое стоит после знака =. В данной задаче это 1.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .let { println(it) }//=1

Решение здесь тривиальное: нужно взять первый  элемент, чтобы получить 1. Применив, например, оператор first ().

listOf(1, 3, 3, 2, 4, 1)
       .first()
       .let { println(it) }//=1

Надеюсь, что правила понятны.

Замечания и допущения

  • Хочу отметить, что из-за разнообразия операторов и по стечению обстоятельств решений может быть несколько. Например, для задачи выше также правильными были бы решения last (), get (0) и так далее.

  • Во всех задачах использован один и тот же список.

  • Не нужно во всех задачах искать логику с точки зрения решения бизнес-задач. Иногда задачи нарочно составлены с ошибками с точки зрения адекватности, сбивающими с толку.

  • Эти упражнения помогут вам не только размять свой мозг, но и узнать о некоторых особенностях операторов, с которыми вы, возможно, не сталкивались.

  • Задачи я старался располагать  от простых к сложным. Но при решении нужно учитывать, что у каждого свой уровень и опыт.

  • Ответы к задачам — в конце статьи, но не спешите скроллить вниз!

  • Не переживайте, если вы не смогли решить все задачи. Они придуманы именно для того, чтобы заставить вас поломать голову. Я сам не смог бы решить их все:)

Итак, приступим.

Задачи

Легкий уровень

Начнем с легких задач. Обратите внимание, что во всех задачах массив одинаковый listOf (1, 3, 3, 2, 4, 1)

Задача 1.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .let { println(it) }//=6

Задача 2.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=5

Задача 3.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=14

Задача 4.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .average()
       .let { println(it) }//=2.5

Обратите внимание, что оператор sum () поменялся. Теперь нужно искать не сумму, а среднее значение. В последующих задачах оператор также будет меняться или вовсе пропадать

Задача 5.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .average()
       .let { println(it) }//=8.0

Средний уровень

Эти задачи будут чуть посложнее и более каверзные.

Задача 6.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=8

Задача 7.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .let { println(it) }//=72

Задача 8.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .let { println(it) }//=null

Задача 9.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .let { println(it) }//=kotlin.Unit

Задача 10.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=15

Задача 11.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .first()
       .let { println(it) }//=java.util.NoSuchElementException

Сложный уровень

Напоследок 3 довольно сложные (с моей точки зрения) задачи.

Задача 12.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=29

Задача 13.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=27

Задача 14.

listOf(1, 3, 3, 2, 4, 1)
       //missed operator
       .sum()
       .let { println(it) }//=6

Замечание: это должен быть не subList ().

Ответы

Задача 1.

listOf(1, 3, 3, 2, 4, 1)
       .count()
       .let { println(it) }//=6

В этой задаче легко догадаться, что в массиве 6 элементов. Чтобы получить это число, нужно воспользоваться оператором count ().

Проверить в Kotlin Playground

Задача 2.

listOf(1, 3, 3, 2, 4, 1)
       .takeLast(2)
       .sum()
       .let { println(it) }//=5

В этой задаче также наглядно видно, что последние 2 числа в сумме дают 5.

Проверить в Kotlin Playground

Задача 3.

listOf(1, 3, 3, 2, 4, 1)
       .map { it }
       .sum()
       .let { println(it) }//=14

Это, скорее, задача-шутка, так как тут ничего не нужно делать со списком, чтобы получить в ответе 14. Но в условии сказано, что нужно добавить один оператор. Оператор, который ничего не делает, — это map { it }. Другие решения типа also{}, let{it} также принимаются.

Проверить в Kotlin Playground

Задача 4.

listOf(1, 3, 3, 2, 4, 1)
       .distinct()
       .average()
       .let { println(it) }//=2.5

Здесь ищем среднее значение из неповторяющихся элементов. Тут было бы уместно начать с подсчета среднего значения — сначала у исходного массива, а далее понять, что нужно каким-то способом это значение уменьшать.

Проверить в Kotlin Playground

Задача 5.

listOf(1, 3, 3, 2, 4, 1)
       .map { 8 }
       .average()
       .let { println(it) }//=8.0

Тут тоже задача-шутка. Сразу понятно, что среднее из текущего листа никак не получить. Один из способов — заменить все числа на необходимые.

Проверить в Kotlin Playground

Задача 6.

listOf(1, 3, 3, 2, 4, 1)
       .filterIndexed { index, value ->
           index % 2 == 0
       }
       .sum()
       .let { println(it) }//=8

В этом случае находим сумму из чисел с четными индексами, то есть из списка listOf (1, 2, 4).

Проверить в Kotlin Playground

Задача 7.

listOf(1, 3, 3, 2, 4, 1)
       .fold(1) { acc, x -> acc * x }
       .let { println(it) }//=72
//or
listOf(1, 3, 3, 2, 4, 1)
       .reduce { acc, x -> acc * x }
       .let { println(it) }//=72

Тут из числа 72 видно, что ожидается большой ответ. Также стоит отметить, что нет оператора sum (). Самый быстрый способ найти решение — начать перемножать. Этого можно достичь с помощью операторов fold () и reduce ().

Проверить в Kotlin Playground

Задача 8.

listOf(1, 3, 3, 2, 4, 1)
       .getOrNull(7)
       .let { println(it) }//=null

В этой задаче нужно было вернуть null. Самый простой способ это сделать — использовать те операторы, которые в наименовании имеют …OrNull (), и подставить туда необходимые для этого условия. Например, вернуть число с индексом больше, чем есть в списке.

Проверить в Kotlin Playground

Задача 9.

listOf(1, 3, 3, 2, 4, 1)
       .forEach { }
       .let { println(it) }//=kotlin.Unit

В этой задаче решение состоит в том, чтобы вернуть значение от оператора, который ничего не возвращает, например forEach { }.

Проверить в Kotlin Playground

Задача 10.

listOf(1, 3, 3, 2, 4, 1)
       .indices
       .sum()
       .let { println(it) }//=15

В этой задаче нужно сложить сумму индексов.

Проверить в Kotlin Playground

Задача 11.

listOf(1, 3, 3, 2, 4, 1)
       .take(0)
       .first()
       .let { println(it) }//=java.util.NoSuchElementException

Эта задача похожа на задачу 8. То есть нужно каким-то способом вернуть то, чего нет в списке, а конкретно — первый элемент. Так как тут стоит именно first (), а не firstOrNull (), то возникнет ошибка. Простой способ сделать список пустым — это take (0).

Проверить в Kotlin Playground

Задача 12.

listOf(1, 3, 3, 2, 4, 1)
       .mapIndexed { index, value ->
           index + value
       }
       .sum()
       .let { println(it) }//=29

В данном случае находится сумма всех чисел и их индексов.

Проверить в Kotlin Playground

Задача 13.

listOf(1, 3, 3, 2, 4, 1)
       .flatMap { 0.rangeTo(it) }
       .sum()
       .let { println(it) }//=27

Эта задача довольно сложная. Здесь нужно вернуть сумму каждого значения в списке и его предшествующим, начиная с 1. То есть для 1: 1, для 3: 1+ 2+ 3, для 2: 1+ 2 и так далее.

Проверить в Kotlin Playground

Задача 14.

listOf(1, 3, 3, 2, 4, 1)
       .distinctBy { it % 3 }
       .sum()
       .let { println(it) }//=6

Эта задача, с моей точки зрения, самая сложная. До ее решения непросто  догадаться. Тут нужно найти сумму уникальных чисел, но не всех, а меньше 4. Уникальных чисел у нас всего 4: 1, 2, 3, 4. Однако остаток от деления на 3 у числа 4 равен 1. Так же как и у 1. Поэтому число 4 исключается из списка.

Проверить в Kotlin Playground

Заключение

Ученый-информатик Дональд Кнут утверждает, что решение логических задач выделяет гормоны, которые повышают уровень счастья. Надеюсь, с вами это произошло!  

Поделитесь в комментариях — удалось ли вам решить все задачи? Возможно, вы нашли что-то новое, чего раньше знали об операторах, либо не придавали этому значения?

Если вы заметили ошибку, также напишите в об этом комментариях. Там же вы можете предложить более интересные решения, если их удалось найти.

© Habrahabr.ru