<repo_name>kiquetal/kotlin-coursera-course<file_sep>/mastermind.kt
package mastermind

data class Evaluation(val rightPosition: Int, val wrongPosition: Int)

fun evaluateGuess(secret: String, guess: String): Evaluation {

    if (secret.equals(guess))
        return Evaluation(4, 0);

    var idx = 0;
    var right = 0;
    var wrong = 0;
    var memo = mutableListOf<Int>();
    for (c in guess) {
        if (c == secret[idx++]) {
            right++
            memo.add(idx -1);
        }
    }
    var newSecret:CharArray=secret.toCharArray()
    var newGuess:CharArray=guess.toCharArray()
    memo.map {

        newSecret[it]='\u0000'
        newGuess[it]='\u0000'
    }
    for (c in newGuess)
    {
         if (c!='\u0000' && newSecret.contains(c))
        {
           newSecret.set(newSecret.indexOf(c),'-')
        }

    }
    for (i in newSecret)
    {
        if (i=='-')
            wrong++
    }
    return Evaluation(right,wrong)
}

fun main()
{
    println("veamos");
}
<file_sep>/Solutions.kt
data class Evaluation(val rightPosition:Int, val wrongPosition:Int)

fun evaluateGuess(secret: String, guess: String): Evaluation {

    val rightPosition = secret.zip(guess).count {
        it.first == it.second
    }
    val commonLetters = "ABCDEF".sumBy {
        Math.min(secret.count {
            it == ch
        },guess.count{
            it == ch
        })
    }

    return Evaluation(rightPosition, commonLetters - rightPosition);

}
<file_sep>/testing.ws.kts
val myList= arrayListOf(113,123,123)
print(myList.count {
    it >120
}>1)

val p= "kiquetal" to arrayListOf(1,2,3)

val fn= (a:String) => {

    return 12
}
fn("hola")
<file_sep>/NiceString.kt
package nicestring

fun String.isNice(): Boolean {
    val nList= this.toCharArray().toList()

    val zipped= nList.zipWithNext()


    val hasIllegal = zipped.none {
            pair -> checkIllegalSubstring(pair)
    }
    val mininumVowels= nList.fold(0){
            acc, character ->
        if (character.isVowel())
            acc+1
        else
            acc
    }
    val hasMinimumVowel= if (mininumVowels>=3) true else false
    val hasDoubleLetter = zipped.any{pair -> isDoubleLetter(pair) }

    val resultsOperations= listOf<Boolean>(hasIllegal,hasMinimumVowel,hasDoubleLetter)

    val onlyTrue= resultsOperations.filter { b ->  b==true }.size
    return onlyTrue>=2
}


fun checkIllegalSubstring(p:Pair<Char,Char>):Boolean
{
    val illegalSubstring= listOf<Pair<Char,Char>>(Pair('b','u'), Pair('b','a'), Pair('b','e'))

    return illegalSubstring.any { pair -> pair==p  }
}




fun Char.isVowel():Boolean {
    val vowels= listOf<Char>('a','e','i','o','u')
    return vowels.contains(this)

}
fun isDoubleLetter(p:Pair<Char,Char>):Boolean {
    return (p.first == p.second)
}

fun main()
{
    val nList= "sisxxjwlkbu".toCharArray().toList()
    println(nList);
    val zipped= nList.zipWithNext()

    print(zipped)


    val hasNoIllegal = zipped.none {
            pair -> checkIllegalSubstring(pair)
    }
    val mininumVowels= nList.fold(0){
            acc, character ->
        if (character.isVowel())
            acc+1
        else
            acc
    }
    val hasMinimumVowel= if (mininumVowels>=3) true else false
    val hasDoubleLetter = zipped.any{pair -> isDoubleLetter(pair) }

    val resultsOperations= listOf<Boolean>(hasNoIllegal,hasMinimumVowel,hasDoubleLetter)

    val onlyTrue= resultsOperations.filter { b ->  b==true }.size
    val isNice= if (onlyTrue>=2) true else false

    println("isNice"+ isNice)






}
fun checkPair(p:Pair<Char,Char>):Boolean{
    println(p.first+"-"+p.second)
    return false
}



<file_sep>/BoardImpl.kt
package board

import board.Direction.*
import java.util.function.Consumer

fun createSquareBoard(width: Int): SquareBoard = MyMatrix(width)
fun <T> createGameBoard(width: Int): GameBoard<T> = MyBoard<T>(width)



class MyMatrix(override val width: Int) : SquareBoard {

    val myCell=Array(width) { row ->
        Array(width) { col ->
            Cell(row + 1, col + 1)
        }
    }

    fun printElement() {
        this.myCell.forEach { arrayOfCells ->

            arrayOfCells.forEach { c->
                println(c)
            }
        }


    }


    fun Array<Array<Cell>>.toMap():MutableMap<Cell,Cell>  {
        val m= mutableMapOf<Cell,Cell>()
        this.forEach { row->
            row.forEach { col  ->
                m[col]=col

            }
        }
        return m;

    }
    private fun isValidPosition(i:Int, j:Int):Boolean {

        return when {
            i<1 -> false
            i>width->false
            j<1 ->false
            j>width->false
            else-> true

        }
    }

    override fun getCellOrNull(i: Int, j: Int): Cell? {

        return if (!isValidPosition(i,j))
            null
        else{
            myCell[i-1][j-1]
        }
    }

    override fun getCell(i: Int, j: Int): Cell {
        require(isValidPosition(i, j)) { "IllegalArgumentException cell does not exist" }
        return myCell[i-1][j-1]

    }


    override fun getAllCells(): Collection<Cell> {
        val m= mutableListOf<Cell>()
        this.myCell.forEach { arrayOfCells ->

            arrayOfCells.forEach { cell->
                m.add(cell)
            }
        }
        return m
    }

    override fun getRow(i: Int, jRange: IntProgression): List<Cell> {

        val m= mutableListOf<Cell>()
        jRange.forEach(Consumer { t ->
            if (this.isValidPosition(i,t))
                m.add(this.getCell(i,t))
        })

        return m

    }

    override fun getColumn(iRange: IntProgression, j: Int): List<Cell> {

        val m= mutableListOf<Cell>()
        iRange.forEach(Consumer { c ->
            println("check valid ${c},${j}"+this.isValidPosition(c,j))
            if (this.isValidPosition(c,j)) {
                m.add(this.getCell(c, j))
            }
        })

        return m
    }

    override fun Cell.getNeighbour(direction: Direction): Cell? {

        return when (direction)
        {
            Direction.UP-> getCellOrNull(this.i-1,this.j)
            Direction.LEFT-> getCellOrNull(this.i,this.j-1)
            Direction.DOWN-> getCellOrNull(this.i+1,this.j)
            Direction.RIGHT-> getCellOrNull(this.i,this.j+1)
        }

    }


}
class MyBoard<T>(override val width: Int) :GameBoard<T>
{

    var myMatrix= mutableMapOf<Cell,T>()
    var m= arrayOfNulls<Any?>(width*width)
    private var idx=0
    override fun getCellOrNull(i: Int, j: Int): Cell? {

        return myMatrix.filterKeys { cell -> cell == Cell(i,j) }.keys.first()
    }

    override fun getCell(i: Int, j: Int): Cell {
        println("getCell"+i+"-"+j)
        println("if emtpy"+myMatrix.isEmpty())
        if (myMatrix.isEmpty()) {
         return   Cell(i,j)
        }
      return when{
               myMatrix.keys.filter { c-> c.i==i && c.j==j }.size>0 -> myMatrix.keys.filter { c-> c.i==i && c.j==j }.first()

           else -> Cell(i,j)


       }

    }

    override fun getAllCells(): Collection<Cell> {
        return myMatrix.keys
    }

    override fun getRow(i: Int, jRange: IntProgression): List<Cell> {
        val myList= arrayListOf<Cell>()
        jRange.forEach{ j ->
            if (myMatrix.filter { entry -> entry.key == Cell(i,j)  }.size>0)
                myList.add(Cell(i,j))
        }
        return myList
    }

    override fun getColumn(iRange: IntProgression, j: Int): List<Cell> {

        val myList= arrayListOf<Cell>()
        iRange.forEach{ l ->
            if (myMatrix.filter { entry -> entry.key == Cell(l,j)  }.size>0)
                myList.add(Cell(l,j))
        }
        return myList
    }

    override fun Cell.getNeighbour(direction: Direction): Cell? {
        return when (direction)
        {
            Direction.UP-> getCellOrNull(this.i-1,this.j-1)
            Direction.LEFT-> getCellOrNull(this.i-i,this.j)
            Direction.DOWN-> getCellOrNull(this.i+1,this.j)
            Direction.RIGHT-> getCellOrNull(this.i,this.j+1)
        }
    }

    override fun get(cell: Cell): T? {

        return myMatrix.get(cell)

    }

    override fun set(cell: Cell, value: T?) {
        println("introducir"+cell + "val" + value)
        if (value != null) {
            myMatrix[cell] = value
            m[idx++]=value
        }
        println(myMatrix)
    }

    override fun filter(predicate: (T?) -> Boolean): Collection<Cell> {
        println(myMatrix)
        return myMatrix.filterValues { predicate(it) }.keys
    }

    override fun find(predicate: (T?) -> Boolean): Cell? {
        return myMatrix.filterValues { predicate(it) }.keys.first()
    }

    override fun any(predicate: (T?) -> Boolean): Boolean {

       return m.any { predicate(it as T?) }

    }

    override fun all(predicate: (T?) -> Boolean): Boolean {
        return m.all { predicate(it as T?) }
    }

}




<file_sep>/pruebas.ws.kts
val listMap = listOf(1,2)
println(listMap)


<file_sep>/Passenger.kt
package taxipark

import java.util.HashSet
import java.util.function.BiFunction
import java.util.function.Consumer
import java.util.function.Function

/*
 * Task #1. Find all the drivers who performed no trips.
 */
fun TaxiPark.findFakeDrivers(): Set<Driver> =

    allDrivers.filter { driver ->
        trips.none { trip ->
            trip.driver == driver
        }
    }.toSet()


/*
 * Task #2. Find all the clients who completed at least the given number of trips.
 */
fun TaxiPark.findFaithfulPassengers(minTrips: Int): Set<Passenger> {

    val newHashMap:HashMap<Passenger,Int> = hashMapOf();
    val allPassenger:HashSet<Passenger> = hashSetOf();
    val entriesMap = trips.fold(newHashMap){
            acc, trip ->
        val passenger=trip.passengers
        passenger.forEach {
            val trips = acc.getOrElse(it) { 0 }
            acc.put(it, trips + 1)
            allPassenger.add(it)

        }
        acc
    }
    if (minTrips<1) return allPassengers

    return entriesMap.filterValues { it>=minTrips }.keys
}

/*
 * Task #3. Find all the passengers, who were taken by a given driver more than once.
 */
fun TaxiPark.findFrequentPassengers(driver: Driver): Set<Passenger> {

    val newHashMap:HashMap<Passenger,ArrayList<Driver>> = hashMapOf();
//    print("driver"+ driver)
    val entriesMap = trips.fold(newHashMap){
            acc, trip ->
        val passenger=trip.passengers
        val n=passenger.map {
            if (acc.containsKey(it))
            {
                if (trip.driver.name == driver.name) {
                    val l = acc.get(it);
                    if (l != null) {
                        l.add(driver)
                    }
                    if (l != null) {
                        acc.put(it, l)
                    }
                }
            }
            else
            {
                if (trip.driver.name == driver.name)
                    acc.put(it, arrayListOf(driver))
            }

        }
        acc
    }

    println(entriesMap)
    return entriesMap.filterValues { it.size>1}.keys
}

/*
 * Task #4. Find the passengers who had a discount for majority of their trips.
 */
fun TaxiPark.findSmartPassengers(): Set<Passenger> =   allPassengers.filter { p ->
    trips.count { t ->
        p in t.passengers && t.discount != null
    } > trips.count { t ->
        p in t.passengers && t.discount == null
    }
}.toSet()


/*
 * Task #5. Find the most frequent trip duration among minute periods 0..9, 10..19, 20..29, and so on.
 * Return any period if many are the most frequent, return `null` if there're no trips.
 */
fun TaxiPark.findTheMostFrequentTripDurationPeriod(): IntRange? {
    if (trips.isEmpty())
        return null

    return trips.groupBy {
        val start = it.duration / 10 * 10
        val end = start + 9
        start..end
    }.maxBy { (_, group) -> group.size }?.key
}

/*
 * Task #6.
 * Check whether 20% of the drivers contribute 80% of the income.
 */
fun TaxiPark.checkParetoPrinciple(): Boolean {
    val totalIncome = trips.sumByDouble { it.cost }

    if (totalIncome.equals(0.0)) {
        return false
    }

    val topDriversIncome =
        trips.groupBy { it.driver }
            .map { (_, list) ->
                list.sumByDouble { it.cost }
            }
            .sortedDescending()

    val top20 = (allDrivers.size * 0.2).toInt()

    return topDriversIncome.take(top20).sum() >= totalIncome * 0.8
}
<file_sep>/rationals.kt
package rationals

import java.lang.IllegalArgumentException
import java.math.BigDecimal
import java.math.BigInteger
import java.math.MathContext


data class Rational(var numerator:BigInteger, var denominator:BigInteger)
{
    init {
        if (denominator.equals(0))
            throw IllegalArgumentException()

        if (denominator<0.toBigInteger())
        {
            numerator=numerator.multiply(-1.toBigInteger())
            denominator=denominator.multiply(-1.toBigInteger())
        }

    }


    operator fun plus(a: Rational): Rational {

        val (numerator, denominator) = a.gcd()

        val d = when (this.denominator) {
            denominator -> this.denominator
            else -> this.denominator.multiply(denominator)
        }


        return when {
            d > denominator -> Rational(
                this.numerator.multiply(denominator).plus(numerator.multiply(this.denominator)),
                d
            )
            else -> Rational(this.numerator.plus(numerator), d)
        }.gcd()

    }

    override fun toString(): String {

        return if (this.denominator==1.toBigInteger())
            this.numerator.toString()
        else {
            val calculated = this.gcd()
            if (calculated.denominator==1.toBigInteger())
                return calculated.numerator.toString()
            return "${calculated.numerator}/${calculated.denominator}"
        }
    }

    operator fun minus(a: Rational): Rational {

        val (numerator, denominator) = a

        val d = when (this.denominator) {
            denominator -> this.denominator
            else -> this.denominator.multiply(denominator)
        }


        return when {
            d > denominator -> Rational(
                this.numerator.multiply(denominator).minus(numerator.multiply(this.denominator)),
                d
            )
            else -> Rational(this.numerator.plus(numerator), d)
        }.gcd()

    }

    operator fun div(a:Rational):Rational{

        val numerator= this.numerator.multiply(a.denominator)
        val denominator = this.denominator.multiply(a.numerator)

        return Rational(numerator,denominator).gcd()
    }

    operator fun times(a:Rational):Rational {

        val numerator= this.numerator.multiply(a.numerator)
        val denominator = this.denominator.multiply(a.denominator)

        return Rational(numerator,denominator).gcd()
    }

    override fun equals(other: Any?): Boolean {

        if (other is Rational){
            val (numerator,denominator) = other.gcd()

            val calculated=this.gcd()

            if (numerator == calculated.numerator && denominator == calculated.denominator) {
                return true
            }
        }
        return false
    }
    operator fun compareTo(a:Rational): Int {

        val div1= this.numerator.toDouble() / this.denominator.toDouble()
        val div2=a.numerator.toDouble() / a.denominator.toDouble()
        if (div1 > div2)
            return 1
        if (div1<div2)
            return -1
        return 0
    }
    operator fun unaryMinus():Rational {

        return Rational(this.numerator.multiply(-1.toBigInteger()),this.denominator).gcd()
    }


  private fun gcd():Rational {

      val gcd=this.numerator.gcd(this.denominator)
      val numerator = this.numerator.divide(gcd)
      val denominator =this.denominator.divide(gcd)
      return Rational(numerator,denominator )

  }
    operator fun rangeTo(a:Rational):Pair<Rational,Rational>{

        return Pair(this,a)

    }




}




fun main() {

    val half = 1 divBy 2
    val third = 1 divBy 3

    val sum: Rational = half + third
    println(5 divBy 6 == sum)


    val difference: Rational = half - third
    println(1 divBy 6 == difference)

    val product: Rational = half * third
    println(1 divBy 6 == product)

    val quotient: Rational = half / third
    println(3 divBy 2 == quotient)

    val negation: Rational = -half
     println(-1 divBy 2 == negation)
    println((2 divBy 1).toString() == "2")

    println((-2 divBy 4).toString() == "-1/2")
    println("117/1098".toRational().toString() == "13/122")

    val twoThirds = 2 divBy 3
    println(half < twoThirds)

    println(half <= twoThirds)
    println(half in third..twoThirds)

    println(2000000000L divBy 4000000000L == 1 divBy 2)


    println("912016490186296920119201192141970416029".toBigInteger() divBy
            "1824032980372593840238402384283940832058".toBigInteger() == 1 divBy 2)

}

<file_sep>/extensions.kt

package rationals

import java.math.BigInteger


operator fun Pair<Rational,Rational>.contains(a:Rational):Boolean {

    if (a>=this.first && a<=this.second)
        return true
    return false

}
infix fun Int.divBy(a:Int): Rational
{
    return Rational(this.toBigInteger(),a.toBigInteger())
}
infix fun Long.divBy(a:Long): Rational
{

    return Rational(BigInteger.valueOf(this),BigInteger.valueOf(a))
}
infix fun BigInteger.divBy(a:BigInteger): Rational
{
    return Rational(this,a)
}
fun String.toRational(): Rational {

    return if (this.length>1 && this.contains("/")) {
        val (numerator, denominator) = this.split("/")
        Rational(numerator.toBigInteger(), denominator.toBigInteger())
    }
    else
        Rational(this.toBigInteger(),1.toBigInteger())
}

