Skip to content

Instantly share code, notes, and snippets.

@theaspect
Last active December 12, 2021 20:06
Show Gist options
  • Save theaspect/a868247739bdb97cf3c35c0d0cafbe08 to your computer and use it in GitHub Desktop.
Save theaspect/a868247739bdb97cf3c35c0d0cafbe08 to your computer and use it in GitHub Desktop.
package com
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.stream.IntStream
import java.util.stream.StreamSupport
import kotlin.collections.ArrayList
import kotlin.streams.toList
import kotlin.time.ExperimentalTime
import kotlin.time.measureTime
// High Order Functions HOF / Функции Высшего Порядка ФВП
// any, fold, filter, map, forEach
// any (T -> Boolean) -> Boolean
// forEach (T -> Unit) -> Unit
// filter (T -> Boolean) -> Collection<T>
// map (T -> R) -> Collection<R>
// fold initial<R>, (accumulator<R>, T -> R) -> R
fun main28() {
// [1,2,3,4,5] -> [2,4,6,8,10] -> ["**","****","******","********","**********"]
val srcList = listOf(1, 2, 3, 4, 5)
val dstList1 = ArrayList<Int>(srcList.size)
for (i in srcList) {
val mappedElement = i * 2 // Подвижная часть
dstList1.add(mappedElement)
}
println(dstList1)
val dstList2 = ArrayList<String>(srcList.size)
for (i in dstList1) {
val mappedElement = "*".repeat(i) // Подвижная часть
dstList2.add(mappedElement)
}
println(dstList2)
// println(listOf(1, 2, 3, 4, 5).myMap { (it * 2).toString() })
// GOF / Gang of Four / Банда Четырех
// Strategy
val srcList2 = listOf(1, 2, 3, 4, 5)
val multiplier = MultiplyByTwo()
val multiplyStrategy = MyStrategy<Int, Int>(multiplier)
val dst2 = multiplyStrategy.function(srcList2)
val repeater = Repeater("_")
val repeatStrategy = MyStrategy(repeater)
val dst3 = repeatStrategy.function(dst2)
println(dst3)
// Chain
val multiplyByTwoRepeater = MultiplyByTwoRepeater("!")
val mB2RStrategy = MyStrategy(multiplyByTwoRepeater)
println(mB2RStrategy.function(srcList2))
// Generic chain
val chainStrategy = MyStrategy(ComposeApplicator(multiplier, repeater))
println(chainStrategy.function(srcList2))
// SAM conversion (Single Abstract Method)
}
interface Applicator<T, R> {
fun apply(input: T): R
}
class MultiplyByTwo : Applicator<Int, Int> {
override fun apply(input: Int): Int {
return input * 2
}
}
class Repeater(val symbol: String) : Applicator<Int, String> {
override fun apply(input: Int): String {
return symbol.repeat(input)
}
}
class MultiplyByTwoRepeater(val symbol: String) : Applicator<Int, String> {
val mBy2 = MultiplyByTwo()
val rep = Repeater(symbol)
override fun apply(input: Int): String {
val res1 = mBy2.apply(input)
val res2 = rep.apply(res1)
return res2
}
}
class ComposeApplicator<A, B, C>(
val applicator1: Applicator<A, B>,
val applicator2: Applicator<B, C>
) :
Applicator<A, C> // (A -> B, B -> C) -> (A -> C)
{
override fun apply(input: A): C {
return applicator2.apply(applicator1.apply(input))
}
}
class MyStrategy<T, R>(val myIface: Applicator<T, R>) {
fun function(input: List<T>): List<R> {
val dst = ArrayList<R>(input.size)
for (i in input) {
val mappedElement = myIface.apply(i) // Подвижная часть
dst.add(mappedElement)
}
return dst
}
}
// Left vs Right fold
// Эквивалентность итерации и рекурсии
// TCO tail call optimization
//(1) 1
//(2) 1
//(3) (1) + (2) == 1 + 1
//(4) (2) + (3) == (2) + ((1) + (2)) == 1 + (1 + 1)
//(5) (3) + (4) == ((1) + (2)) + ((2) + (3)) == ((1) + (2)) + ((2) + ((1) + (2))) == ((1 + 1) + 1) + (1 + 1)
//(6) (4) + (5) == ((2) + (3)) + ((3) + (4)) == ((2) + ((1) + (2))) + (((1) + (2)) + ((2) + (3))) == ... == ((1 + 1) + 1) + ((1 + 1) + 1) + (1 + 1)
fun fibi(n: Long): Long {
var a1: Long = 1
var a2: Long = 1
for (i in 3..n) {
val a3 = a1 + a2
a1 = a2
a2 = a3
}
return a2
}
// Нельзя пометить как tailrec потому что последняя операция это сумма
fun fib(n: Long): Long = when {
n <= 2 -> 1
else -> fib(n - 1) + fib(n - 2)
}
data class Tuple(val a1: Long, val a2: Long, val n: Long)
// Итерация справа налево
fun fibr(t: Tuple): Tuple {
return if (t.n <= 0) t
else fibr(Tuple(t.a2, t.a1 + t.a2, t.n - 1))
}
// Итерация слева направо
fun fibrl(n: Long, a1: Long = 0, a2: Long = 1): Long {
return if (n <= 0) a1
else fibrl(n - 1, a2, a1 + a2)
}
// https://kotlinlang.org/docs/reference/functions.html#tail-recursive-functions
tailrec fun fibrl2(n: Long, a1: Long = 0, a2: Long = 1): Long {
return if (n <= 0) a1
else fibrl2(n - 1, a2, a1 + a2)
}
class Fibonacci : Iterator<Long> {
var a1 = 1L
var a2 = 1L
override fun hasNext(): Boolean = true
override fun next(): Long {
val cur = a1
a1 = a2
a2 += cur
println("= $a1 $a2")
return cur
}
}
class FibIterable : Iterable<Long> {
override fun iterator(): Iterator<Long> {
return Fibonacci()
}
}
fun main() {
// println(fib(1))
// println(fib(2))
// println(fib(3))
// println(fib(10))
// // println(fib(50))
//
// println(fibi(1))
// println(fibi(2))
// println(fibi(3))
// println(fibi(4))
// println(fibi(5))
// println(fibi(50))
//
// println(fibrl(1))
// println(fibrl(2))
// println(fibrl(3))
// println(fibrl(4))
// println(fibrl(5))
// println(fibrl(50))
// println(fibrl(1_000_000)) // StackOverflowError
println(fibrl2(1_000_000))
val fibIter = Fibonacci()
for (i in 1..5) {
println(fibIter.next())
}
// Бесконечная генерация значений
// for (i in fibIter) {
// println(i)
// }
println("Sequence!")
// Lazy Evaluation / Ленивые вычисления
// take, filter, map - intermediate, промежуточные функции, не приводят к вычислению последовательности
println(Fibonacci().asSequence().take(10).filter { it % 2L == 1L }.map { it })
println("Sequence List!")
// find - terminal, завершающая функция, приводит к вычислению последовательности
println(Fibonacci().asSequence()
.take(100)
.filter {
println("# $it")
it % 2L == 1L
}
.find {
println("? $it")
it > 100
}
)
println("Koltin collections")
println(FibIterable()
.take(20)
.filter {
println("!! $it")
it % 2L == 1L
}
.find {
println("** $it")
it > 100
}
)
println("Lazy/Non Lazy")
println(Fibonacci().asSequence().take(5))
println(FibIterable().take(5))
}
// HOF
// ФВП
class Receiver {
fun doSmth(strategy: IStrategy<List<Int>, Int>) =
strategy.execute(listOf(1, 2, 3, 4, 5))
}
@FunctionalInterface
interface IStrategy<T, R> {
fun execute(input: T): R
}
class Counter : IStrategy<List<Int>, Int> {
override fun execute(input: List<Int>): Int =
input.count()
}
class Adder : IStrategy<List<Int>, Int> {
override fun execute(input: List<Int>): Int =
input.sum()
}
class Receiver2 {
fun doSmth(strategy: (List<Int>) -> Int) =
strategy(listOf(1, 2, 3, 4, 5))
}
fun main4() {
println(Receiver().doSmth(Counter()))
println(Receiver().doSmth(Adder()))
// println(Receiver2().doSmth({i: List<Int> -> i.sum() }))
// println(Receiver2().doSmth { i: List<Int> -> i.sum() })
// println(Receiver2().doSmth { i -> i.sum() })
println(Receiver2().doSmth { it.count() })
println(Receiver2().doSmth { it.sum() })
}
fun main5() {
// map/collect, filter/find, reduce/fold/inject
// foreach
// [1,2,3,4,5,6] -> [x]
// Sum
// listOf(1, 2, 3, 4, 5).fold(0, {acc, current -> acc + current })
val f1 = listOf(1, 2, 3, 4, 5).fold(0) { acc, current ->
acc + current
}
println(f1)
// count
val f2 = listOf(1, 2, 3, 4, 5).fold(0) { acc, current ->
acc + 1
}
println(f2)
// a, b :: collection
// a -> b
// size(a) == size(b)
// map
// [a, b, c] -> [a1, b1, c1]
// toStr Collection<Int> -> Collection<String>
val f3 = listOf(1, 2, 3, 4, 5).map { current -> "!$current!" }
println(f3)
// +10 Collection<Int> -> Collection<Int>
// val f4 = listOf(1, 2, 3, 4, 5).map { current -> current + 10 }
val f4 = listOf(1, 2, 3, 4, 5).map { it + 10 } // если анонимная функция содержит 1 элемент
println(f4)
// a, b :: collection
// filter
// a -> b
// T -> T
// size(a) <= size(b)
// [a, b, c] -> [a, c]
val f5 = listOf(1, 2, 3, 4, 5).filter { it % 2 == 0 }
println(f5)
val f6 = listOf(1, 2, 3, 4, 5).reversed().filterIndexed { index, elem -> index % 2 == 0 }
println(f6)
// map via fold
// + 10
val f7 = listOf(1, 2, 3, 4, 5).fold(emptyList<Int>()) { acc, current ->
// acc.plus(current + 10)
// acc + (current + 10) // [] + elem
acc + listOf(current + 10) // [] + []
}
println(f7)
// filter via fold
// odd elements
val f8 = listOf(1, 2, 3, 4, 5).fold(emptyList<Int>()) { acc, current ->
// return@fold if (current % 2 == 0) {
// acc + current
// } else {
// acc
// }
if (current % 2 == 0) acc + current else acc
}
println(f8)
}
@ExperimentalTime
fun main6() {
// stream vs map
// map > filter > reduce
println("Begin2")
println(measureTime {
//val res = IntStream.range(0, 1_000_000_000).map {
val res = IntStream.range(0, 10_000_000).map {
// Thread.sleep(1)
it * 10
}.map {
it + 1
}
// }.mapToObj {
// it.toString()
// }
//.limit(10)
.reduce { acc, i -> acc + i }
println(res)
})
println("Begin1")
println(measureTime {
val res = (0..10_000_000).map {
// Thread.sleep(1)
it * 10
}.map {
it + 1
}.map {
// it.toString()
it
}.take(10)
// }.filterIndexed { i, e ->
// i < 10
// }
.reduce { acc, i ->
acc + i
}
println(res)
})
println("Begin3")
println(measureTime {
val res = IntStream.range(0, 10_000_000).map {
// Thread.sleep(1)
it * 10
}.map {
it + 1
}.mapToObj {
it.toString()
}
//.limit(10)
//.reduce { acc, i -> acc + i }
println(res)
})
}
@ExperimentalTime
fun main7() {
fun mul(i: Int): Int = i * 10
fun add(i: Int): Int = i + 1
fun compose(i: Int): Int = add(mul(i))
println(measureTime {
val res1 = (0..10_000_000).map(::mul).map(::add).reduce { acc, i -> acc + i }
println(res1)
})
println(measureTime {
//val res1 = (0..10_000_000).map { it -> compose(it) }.reduce { acc, i -> acc + i }
val res1 = (0..10_000_000).map(::compose).reduce { acc, i -> acc + i }
println(res1)
})
}
//<- foldl == foldleft
//[1, 2, 3, 4]
// tailrec
fun fibRec(n: Long): Long =
when {
n <= 1 -> 1
else -> fibRec(n - 1) + fibRec(n - 2)
}
//-> foldr == foldright
//[1, 2, 3, 4]
fun fibRecTail(n: Long) = fibRecTail(0, n, 1, 1)
tailrec fun fibRecTail(i: Long, max: Long, iMinus1: Long, cur: Long): Long {
return when {
i >= max -> cur
else -> {
val next = iMinus1 + cur
fibRecTail(i + 1, max, cur, next)
}
}
}
/*
[0, -, -] -> a
[1, -, -] -> b
[2, a, b] -> c = a + b
[3, b, c] -> d = b + c
*/
class FibGenerator {
private var cur: Long = 1
private var prev: Long = 1
fun hasNext() = true
fun next(): Long {
val next = cur + prev
prev = cur
cur = next
return cur
}
}
class FibIterator : Iterator<Long> {
private var cur: Long = 1
private var prev: Long = 1
override fun hasNext() = true
override fun next(): Long {
val next = cur + prev
prev = cur
cur = next
return cur
}
}
class C : AutoCloseable {
override fun close() {
println("closed")
}
}
class MyWrap {
fun wrap(lambda: () -> String) {
println("Begin")
lambda()
println("end")
}
}
class D {
fun x(): String {
val use = C().use {
println("opened")
//return@use "a"
return@x "asd"
}
return ""
}
// fun y(): String {
// MyWrap().wrap {
// println("Inside")
// return "blabla"
// }
// }
}
@ExperimentalTime
fun main8() {
D().x()
println(measureTime {
println(fibRec(40))
})
// println(fibRecTail(0))
// println(fibRecTail(1))
// println(fibRecTail(2))
// println(fibRecTail(3))
// println(fibRecTail(4))
// println(fibRecTail(5))
println(measureTime {
println(fibRecTail(100))
})
println("Generator")
println(measureTime {
val gen = FibGenerator()
for (i in 0..98) {
gen.next()
}
println(gen.next())
})
println("Stream")
println(measureTime {
val fibStream = StreamSupport.stream(FibIterator().asSequence().asIterable().spliterator(), false)
println(fibStream.limit(20).toList())
val fibStream2 = StreamSupport.stream(FibIterator().asSequence().asIterable().spliterator(), false)
println(fibStream2.skip(99).limit(1).toList()[0])
// for (i in FibIterator()) {
// println(i)
// }
println(Random().ints().limit(100).toList())
})
}
fun main20() {
val async1: CompletableFuture<Int> = CompletableFuture.supplyAsync {
println("${Thread.currentThread().id}: Inside")
Thread.sleep(3000)
println("${Thread.currentThread().id}: End Sleep")
10
}
val async2: CompletableFuture<Int> = CompletableFuture.supplyAsync {
println("${Thread.currentThread().id}: Inside")
Thread.sleep(3000)
println("${Thread.currentThread().id}: End Sleep")
20
}
async1.thenAccept { result ->
println("Callback on result: $result ${Thread.currentThread().id}")
}
CompletableFuture.allOf(async1, async2).thenAccept {
println("${Thread.currentThread().id}: Wait for two")
println("${Thread.currentThread().id}: async1 ${async1.get()}")
println("${Thread.currentThread().id}: async2 ${async2.get()}")
}
for (i in 0..5) {
if (async1.isDone) {
println("Result: ${async1.get()}")
} else {
println("Not Yet1 in ${Thread.currentThread().id}")
Thread.sleep(1000)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment