-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a49ba2e
Showing
9 changed files
with
396 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: Repo Admin | ||
on: | ||
push: | ||
branches: [ main ] | ||
paths: | ||
- doc/* | ||
- src/*/*.scala | ||
jobs: | ||
admin: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
contents: write | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
- name: Tidy repository | ||
uses: propensive/tumult@0.5.8 | ||
- name: Autocommit changes | ||
uses: stefanzweifel/git-auto-commit-action@v4 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: Build | ||
on: | ||
push: | ||
branches: [ main ] | ||
pull_request: | ||
branches: [ main ] | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v3 | ||
with: | ||
submodules: recursive | ||
- name: Setup Java 19 | ||
uses: actions/setup-java@v3 | ||
with: | ||
distribution: 'temurin' | ||
java-version: '19' | ||
- name: Get Wrath | ||
uses: actions/checkout@v3 | ||
with: | ||
repository: 'propensive/wrath' | ||
path: 'wrath' | ||
ref: '0.6.1' | ||
- name: Build | ||
run: "wrath/wrath -F -x" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
name: Publish | ||
on: | ||
push: | ||
tags: | ||
- 'pending/*' | ||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Checkout | ||
uses: actions/checkout@v2 | ||
with: | ||
submodules: recursive | ||
fetch-depth: 0 | ||
- name: Setup Java 11 | ||
uses: actions/setup-java@v2 | ||
with: | ||
distribution: 'temurin' | ||
java-version: '11' | ||
- name: Fetch tags | ||
run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* | ||
- name: Get Version | ||
id: tagName | ||
run: echo ::set-output name=version::${GITHUB_REF#refs/tags/pending/} | ||
- name: 'Abort if tag exists' | ||
id: checkTagged | ||
shell: bash | ||
run: git show-ref --tags --verify --quiet -- "refs/tags/release/${{ steps.tagName.outputs.version }}" && exit 1 || exit 0 | ||
- name: Publish | ||
run: echo Publishing | ||
- name: Tag release | ||
uses: actions/github-script@v6 | ||
with: | ||
github-token: ${{ secrets.RELEASE_TOKEN }} | ||
script: | | ||
let newRef = context.ref.replace('pending', 'release'); | ||
github.rest.git.createRef({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
ref: newRef, | ||
sha: context.sha | ||
}); | ||
github.rest.git.deleteRef({ | ||
owner: context.repo.owner, | ||
repo: context.repo.repo, | ||
ref: context.ref.substring(5) | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# This is a buildfile for Fury or Wrath. | ||
# More information is available at: https://github.com/propensive/wrath/ | ||
|
||
target metamorphose/test | ||
|
||
repo propensive/probably | ||
|
||
project metamorphose | ||
module core | ||
compiler scala | ||
sources src/core | ||
include fulminate/core contingency/core | ||
|
||
module test | ||
compiler scala | ||
sources src/test | ||
include probably/cli metamorphose/core | ||
main metamorphose.Tests | ||
coverage metamorphose/core |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package metamorphose | ||
|
||
import contingency.* | ||
|
||
import scala.annotation.* | ||
|
||
case class Factoradic(number: BigInt): | ||
def expand: List[Int] = | ||
@tailrec | ||
def recur(current: BigInt, sequence: List[BigInt], result: List[Int]): List[Int] = | ||
sequence match | ||
case Nil => | ||
result.reverse | ||
|
||
case head :: tail => | ||
val next = (current/head).toInt | ||
recur(current - next*head, tail, next :: result) | ||
|
||
if number == 0 then Nil | ||
else recur(number, Factorial.sequence(Factorial.magnitude(number) - 1), Nil) | ||
|
||
object Factoradic: | ||
def apply(sequence: List[Int]): Factoradic raises PermutationError = | ||
def recur(sequence: List[Int], bases: List[BigInt], result: BigInt, base: Int): BigInt = | ||
sequence match | ||
case Nil => result | ||
case head :: tail => | ||
if head >= base | ||
then raise(PermutationError(PermutationError.Reason.BaseRange(head, base)))(()) | ||
|
||
recur(tail, bases.tail, result + bases.head*head, base - 1) | ||
|
||
val length = sequence.length | ||
Factoradic(recur(sequence, Factorial.sequence(length), 0, length)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package metamorphose | ||
|
||
import scala.annotation.* | ||
|
||
object Factorial: | ||
def apply(n: Int): BigInt = | ||
@tailrec | ||
def recur(i: Int, result: BigInt): BigInt = if i == 0 then result else recur(i - 1, result*i) | ||
|
||
recur(n, 1) | ||
|
||
def magnitude(n: BigInt): Int = | ||
@tailrec | ||
def recur(i: Int, result: BigInt): Int = if result > n then i else recur(i + 1, result*i) | ||
|
||
recur(1, 1) | ||
|
||
def sequence(n: Int): List[BigInt] = | ||
@tailrec | ||
def recur(i: Int, result: List[BigInt]): List[BigInt] = | ||
if i == n then result else recur(i + 1, result.head*i :: result) | ||
|
||
recur(1, List(1)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package metamorphose | ||
|
||
import scala.collection.mutable.BitSet | ||
import scala.annotation.* | ||
|
||
import contingency.* | ||
|
||
object Permutation: | ||
|
||
def bySize(n: Int): LazyList[Permutation] = LazyList.range[BigInt](0, Factorial(n)).map: i => | ||
Permutation(Factoradic(i)) | ||
|
||
def apply(sequence: IndexedSeq[Int]): Permutation raises PermutationError = | ||
val array: Array[Int] = new Array(sequence.length) | ||
val seen: BitSet = BitSet() | ||
|
||
for index <- sequence.indices do | ||
val element = sequence(index) | ||
array(index) = element - seen.count(_ < element) | ||
|
||
if element >= sequence.length || element < 0 | ||
then | ||
raise | ||
(PermutationError(PermutationError.Reason.InvalidIndex(element, sequence.length - 1)))(()) | ||
|
||
if seen.contains(element) | ||
then raise(PermutationError(PermutationError.Reason.DuplicateIndex(element, index)))(()) | ||
|
||
seen(element) = true | ||
|
||
Permutation(Factoradic(array.to(List))) | ||
|
||
case class Permutation(factoradic: Factoradic): | ||
lazy val lehmer: List[Int] = factoradic.expand | ||
lazy val expansion: List[Int] = unsafely(apply[Int](List.range(0, lehmer.length))) | ||
|
||
def apply(n: Int): Int = expansion(n) | ||
|
||
def apply[ElementType](sequence: List[ElementType]): List[ElementType] raises PermutationError = | ||
if sequence.length < lehmer.length then | ||
raise(PermutationError(PermutationError.Reason.TooShort(sequence.length, lehmer.length)))(()) | ||
|
||
def recur | ||
(lehmer: List[Int], | ||
prefix: List[ElementType], | ||
list: List[ElementType], | ||
current: Int, | ||
result: List[ElementType]) | ||
: List[ElementType] = | ||
|
||
lehmer match | ||
case head :: tail => | ||
if current == head | ||
then recur(tail, prefix, list.tail, current, list.head :: result) | ||
else | ||
if current < head | ||
then recur(lehmer, list.head :: prefix, list.tail, current + 1, result) | ||
else recur(lehmer, prefix.tail, prefix.head :: list, current - 1, result) | ||
|
||
case Nil => | ||
result.reverse | ||
|
||
val prefix = sequence.length - lehmer.length | ||
sequence.take(prefix) ::: recur(lehmer, Nil, sequence.drop(prefix), 0, Nil) | ||
|
||
def inverse: Permutation = if lehmer.isEmpty then this else | ||
val length = lehmer.length | ||
val array: Array[Int] = new Array(lehmer.length) | ||
|
||
def recur(index: Int, sequence: List[Int]): Permutation = sequence match | ||
case head :: tail => | ||
array(head) = index | ||
recur(index + 1, tail) | ||
|
||
case Nil => | ||
unsafely(Permutation(IArray.from(array))) | ||
|
||
recur(0, expansion) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package metamorphose | ||
|
||
import fulminate.* | ||
|
||
object PermutationError: | ||
enum Reason: | ||
case BaseRange(value: Int, base: Int) | ||
case DuplicateIndex(index: Int, element: Int) | ||
case InvalidIndex(last: Int, max: Int) | ||
case TooShort(length: Int, min: Int) | ||
|
||
import Reason.* | ||
|
||
given Reason is Communicable = | ||
case BaseRange(value, base) => | ||
msg"the value $value is too large for its positional base $base" | ||
|
||
case DuplicateIndex(element, index) => | ||
msg"the index $element was duplicated at $index" | ||
|
||
case InvalidIndex(index, max) => | ||
msg"the index $index appears, but every index should be in the range 0-$max" | ||
|
||
case TooShort(size, min) => | ||
msg"the input, of size $size, is too short for the permutation of size $min" | ||
|
||
case class PermutationError(reason: PermutationError.Reason) | ||
extends Error(msg"could not construct permutation because $reason") |
Oops, something went wrong.