Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelbull committed Mar 3, 2024
0 parents commit 9f09ab2
Show file tree
Hide file tree
Showing 26 changed files with 3,735 additions and 0 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.yaml]
indent_size = 2
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.bat text eol=crlf
127 changes: 127 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
name: CI

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

permissions:
contents: read

jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
tasks: build

- os: macos-latest
tasks: >
iosX64Test
macosX64Test
tvosX64Test
watchosX64Test
- os: windows-latest
tasks: mingwX64Test

runs-on: ${{ matrix.os }}

steps:
- name: Checkout Project
uses: actions/checkout@v4

- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2

- uses: actions/cache@v4
with:
path: |
~/.konan
key: ${{ runner.os }}-${{ hashFiles('**/.lock') }}

- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Build with Gradle Wrapper
run: ./gradlew ${{ matrix.tasks }}

publish:
needs: build
if: github.ref == 'refs/heads/master' && github.event_name == 'push' && needs.build.result == 'success'

strategy:
matrix:
include:
- os: ubuntu-latest
tasks: >
publishAndroidNativeArm32PublicationToMavenRepository
publishAndroidNativeArm64PublicationToMavenRepository
publishAndroidNativeX64PublicationToMavenRepository
publishAndroidNativeX86PublicationToMavenRepository
publishJsPublicationToMavenRepository
publishJvmPublicationToMavenRepository
publishKotlinMultiplatformPublicationToMavenRepository
publishLinuxArm64PublicationToMavenRepository
publishLinuxX64PublicationToMavenRepository
publishWasmJsPublicationToMavenRepository
- os: windows-latest
tasks: publishMingwX64PublicationToMavenRepository

- os: macos-latest
tasks: >
publishIosArm64PublicationToMavenRepository
publishIosSimulatorArm64PublicationToMavenRepository
publishIosX64PublicationToMavenRepository
publishMacosArm64PublicationToMavenRepository
publishMacosX64PublicationToMavenRepository
publishTvosArm64PublicationToMavenRepository
publishTvosSimulatorArm64PublicationToMavenRepository
publishTvosX64PublicationToMavenRepository
publishWatchosArm32PublicationToMavenRepository
publishWatchosArm64PublicationToMavenRepository
publishWatchosSimulatorArm64PublicationToMavenRepository
publishWatchosX64PublicationToMavenRepository
runs-on: ${{ matrix.os }}

env:
ORG_GRADLE_PROJECT_ossrhUsername: ${{ secrets.OSSRH_USERNAME }}
ORG_GRADLE_PROJECT_ossrhPassword: ${{ secrets.OSSRH_PASSWORD }}
ORG_GRADLE_PROJECT_signingKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingKey: ${{ secrets.SIGNING_KEY }}
ORG_GRADLE_PROJECT_signingPassword: ${{ secrets.SIGNING_PASSWORD }}

steps:
- name: Checkout Project
uses: actions/checkout@v4

- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v2

- uses: actions/cache@v4
with:
path: |
~/.konan
key: ${{ runner.os }}-${{ hashFiles('**/.lock') }}

- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 8

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Publish with Gradle Wrapper
run: ./gradlew ${{ matrix.tasks }}
28 changes: 28 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Hidden files
.*

# Temporary files
*~

# Git
!.git*

# GitHub
!/.github

# EditorConfig
!.editorconfig

# IntelliJ Idea
out/
*.iml
*.ipr
*.iws

# Gradle
build/
local.properties

# JVM error logs
hs_err_pid*.log
replay_pid*.log
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2024 Michael Bull (https://www.michael-bull.com)

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
208 changes: 208 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# kotlin-itertools

[![Maven Central](https://img.shields.io/maven-central/v/com.michael-bull.kotlin-itertools/kotlin-itertools.svg)](https://search.maven.org/search?q=g:com.michael-bull.kotlin-itertools)
[![CI](https://github.com/michaelbull/kotlin-itertools/actions/workflows/ci.yaml/badge.svg)](https://github.com/michaelbull/kotlin-itertools/actions/workflows/ci.yaml)
[![License](https://img.shields.io/github/license/michaelbull/kotlin-itertools.svg)](https://github.com/michaelbull/kotlin-itertools/blob/master/LICENSE)

![badge][badge-android]
![badge][badge-jvm]
![badge][badge-js]
![badge][badge-nodejs]
![badge][badge-linux]
![badge][badge-windows]
![badge][badge-wasm]
![badge][badge-ios]
![badge][badge-mac]
![badge][badge-tvos]
![badge][badge-watchos]
![badge][badge-js-ir]
![badge][badge-android-native]
![badge][badge-apple-silicon]

Multiplatform combinatoric sequences for Kotlin, inspired by [python-itertools][python-itertools].

Initially built as part of my solutions for [Advent of Code 2023][advent-2023].

## Installation

```groovy
repositories {
mavenCentral()
}
dependencies {
implementation("com.michael-bull.kotlin-itertools:kotlin-itertools:1.0.0")
}
```

## Sequences

### Combinations

```kotlin
fun <T> List<T>.combinations(length: Int = size): Sequence<List<T>>

fun <T> List<T>.pairCombinations(): Sequence<Pair<T, T>>

fun <T> List<T>.tripleCombinations(): Sequence<Triple<T, T, T>>
```

Returns a sequence that yields `length`-sized combinations from this list.

The combination tuples are emitted in lexicographic order according to the order of this list.

<details>
<summary><strong>Examples</strong></summary>

```kotlin
import com.github.michaelbull.itertools.combinations
import com.github.michaelbull.itertools.pairCombinations
import com.github.michaelbull.itertools.tripleCombinations

// [[A, B], [A, C], [A, D], [B, C], [B, D], [C, D]]
fun example1(): List<List<Char>> {
return "ABCD".toList()
.combinations(length = 2)
.toList()
}

// [(A, B), (A, D), (A, C), (B, D), (B, C), (D, C)]
fun example2(): List<Pair<Char, Char>> {
return "ABDC".toList()
.pairCombinations()
.toList()
}

// [(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
fun example3(): List<Triple<Int, Int, Int>> {
return (0..3).toList()
.tripleCombinations()
.toList()
}
```
</details>

### Permutations

```kotlin
fun <T> List<T>.permutations(length: Int = size): Sequence<List<T>>

fun <T> List<T>.pairPermutations(): Sequence<Pair<T, T>>

fun <T> List<T>.triplePermutations(): Sequence<Triple<T, T, T>>
```

Returns a sequence that yields `length`-sized permutations from this list.

The permutation tuples are emitted in lexicographic order according to the order of this list.

<details>
<summary><strong>Examples</strong></summary>

```kotlin
import com.github.michaelbull.itertools.permutations
import com.github.michaelbull.itertools.pairPermutations
import com.github.michaelbull.itertools.triplePermutations

// [[A, B], [A, C], [A, D], [B, A], [B, C], [B, D], [C, A], [C, B], [C, D], [D, A], [D, B], [D, C]]
fun example1(): List<List<Char>> {
return "ABCD".toList()
.permutations(length = 2)
.toList()
}

// [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
fun example2(): List<Pair<Int, Int>> {
return (0..2).toList()
.pairPermutations()
.toList()
}

// [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)]
fun example3(): List<Triple<Int, Int, Int>> {
return (0..2).toList()
.triplePermutations()
.toList()
}
```
</details>

### Cartesian Product

```kotlin
fun <A, B> Iterable<A>.product(other: Iterable<B>): Sequence<Pair<A, B>>
fun <A, B, C> Iterable<A>.product(first: Iterable<B>, second: Iterable<C>): Sequence<Triple<A, B, C>>

fun <A, B> Pair<Iterable<A>, Iterable<B>>.product(): Sequence<Pair<A, B>>
fun <A, B, C> Triple<Iterable<A>, Iterable<B>, Iterable<C>>.product(): Sequence<Triple<A, B, C>>

fun <T> List<List<T>>.product(): Sequence<List<T>>
```

Returns a sequence that yields the Cartesian product of the input iterables/lists.

The product tuples are emitted in lexicographic order according to the order of this iterable/list.

<details>
<summary><strong>Examples</strong></summary>

```kotlin
import com.github.michaelbull.itertools.product

// [(A, x), (A, y), (B, x), (B, y), (C, x), (C, y), (D, x), (D, y)]
fun example1(): List<Pair<Char, Char>> {
val a = "ABCD".toList()
val b = "xy".toList()
return a.product(b).toList()
}

// [(A, C, E), (A, C, F), (A, D, E), (A, D, F), (B, C, E), (B, C, F), (B, D, E), (B, D, F)]
fun example2(): List<Triple<Char, Char, Char>> {
val a = "AB".toList()
val b = "CD".toList()
val c = "EF".toList()

return Triple(a, b, c)
.product()
.toList()
}

// [[A, x], [A, y], [B, x], [B, y], [C, x], [C, y], [D, x], [D, y]]
fun example3(): List<List<Char>> {
val a = "ABCD".toList()
val b = "xy".toList()

return listOf(a, b)
.product()
.toList()
}
```
</details>

## Contributing

Bug reports and pull requests are welcome on [GitHub][github].

## License

This project is available under the terms of the ISC license. See the
[`LICENSE`](LICENSE) file for the copyright information and licensing terms.

[python-itertools]: https://docs.python.org/3/library/itertools.html
[advent-2023]: https://github.com/michaelbull/advent-2023
[github]: https://github.com/michaelbull/kotlin-itertools

[badge-android]: http://img.shields.io/badge/-android-6EDB8D.svg?style=flat
[badge-android-native]: http://img.shields.io/badge/support-[AndroidNative]-6EDB8D.svg?style=flat
[badge-jvm]: http://img.shields.io/badge/-jvm-DB413D.svg?style=flat
[badge-js]: http://img.shields.io/badge/-js-F8DB5D.svg?style=flat
[badge-js-ir]: https://img.shields.io/badge/support-[IR]-AAC4E0.svg?style=flat
[badge-nodejs]: https://img.shields.io/badge/-nodejs-68a063.svg?style=flat
[badge-linux]: http://img.shields.io/badge/-linux-2D3F6C.svg?style=flat
[badge-windows]: http://img.shields.io/badge/-windows-4D76CD.svg?style=flat
[badge-wasm]: https://img.shields.io/badge/-wasm-624FE8.svg?style=flat
[badge-apple-silicon]: http://img.shields.io/badge/support-[AppleSilicon]-43BBFF.svg?style=flat
[badge-ios]: http://img.shields.io/badge/-ios-CDCDCD.svg?style=flat
[badge-mac]: http://img.shields.io/badge/-macos-111111.svg?style=flat
[badge-watchos]: http://img.shields.io/badge/-watchos-C0C0C0.svg?style=flat
[badge-tvos]: http://img.shields.io/badge/-tvos-808080.svg?style=flat
Loading

0 comments on commit 9f09ab2

Please sign in to comment.