├── .github └── dependabot.yml ├── .gitignore ├── Functional Programming in Java, Groovy, and Kotlin.pdf ├── README.md ├── antarctic_script.kts ├── build.gradle.kts ├── flickr_key.txt ├── gradle ├── libs.versions.toml ├── libs.versions.updates.toml └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── src ├── main ├── groovy │ ├── collectors │ │ └── adding_books_to_map.groovy │ ├── datetime │ │ ├── AntarcticaTimeZones.java │ │ ├── CTtoIndia.java │ │ ├── FunnyOffsets.java │ │ ├── antarctica.groovy │ │ └── ct_india.groovy │ ├── flickr │ │ ├── cat_pictures.groovy │ │ ├── cats.json │ │ └── flickr_key.txt │ ├── functional │ │ ├── annotations │ │ │ ├── AnnotatedFunctions.groovy │ │ │ ├── UseAnnotatedFunctions.java │ │ │ ├── memoize.groovy │ │ │ ├── tail_recursive.groovy │ │ │ └── trampoline.groovy │ │ ├── executable_class.groovy │ │ ├── immutables │ │ │ ├── Point.groovy │ │ │ └── UsePoint.java │ │ ├── map_filter_reduce.groovy │ │ └── using_inject.groovy │ ├── geocoder │ │ ├── Geocoder.groovy │ │ └── Location.java │ ├── io │ │ └── Jumble.groovy │ ├── lambdas │ │ ├── PrimeCheckerGroovy.groovy │ │ ├── closures.groovy │ │ ├── composition.groovy │ │ ├── currying.groovy │ │ ├── lambdas.groovy │ │ ├── map_filter_reduce.groovy │ │ └── method_references.groovy │ ├── metaprogramming │ │ ├── pirate.groovy │ │ └── pirate_key.txt │ ├── sorting │ │ ├── GolfersCS.groovy │ │ ├── GroovyGolfer.groovy │ │ ├── SortingDemoGroovy.groovy │ │ └── sort_groovy_golfers.groovy │ └── streams │ │ ├── LazyStreamsGroovy.groovy │ │ └── StreamsDemo.java ├── java │ ├── collectors │ │ ├── AddCollectionToMap.java │ │ └── Book.java │ ├── composition │ │ └── CombineLambdas.java │ ├── io │ │ └── JumbleJava.java │ ├── lambdas │ │ ├── LambdaDemo.java │ │ └── PrimeChecker.java │ ├── sorting │ │ ├── Golfer.java │ │ ├── SortGolfers.java │ │ └── SortingDemo.java │ └── streams │ │ ├── LazyStreams.java │ │ ├── MapFilterReduce.java │ │ ├── RandomStreams.java │ │ └── SumNumbers.java ├── kotlin │ ├── astro │ │ ├── AstroRequest.kt │ │ └── AstroResult.kt │ ├── coroutines │ │ └── downloadImages.kt │ ├── extension │ │ ├── Yoda.kt │ │ └── palindrome.kt │ ├── flickr │ │ └── FlickrGateway.kt │ ├── functional │ │ ├── algorithms.kt │ │ ├── composition.kt │ │ └── primes.kt │ ├── io │ │ └── jumble.kt │ ├── lambdas │ │ └── map_filter_reduce.kt │ ├── scripts │ │ └── antarctica.kt │ └── sequences │ │ ├── lazysequences.kt │ │ ├── sequenceFunction.kt │ │ └── sum_numbers.kt └── resources │ ├── dict │ ├── README │ ├── connectives │ ├── propernames │ ├── web2 │ ├── web2a │ └── words │ ├── strings.txt │ └── yoda_key.txt └── test ├── groovy ├── functional │ ├── annotations │ │ └── AnnotatedFunctionsTest.groovy │ └── immutables │ │ └── PointSpec.groovy ├── io │ └── JumbleSpec.groovy ├── lambdas │ └── PrimeCheckerSpec.groovy ├── sorting │ └── SortingDemoGroovySpec.groovy └── streams │ ├── LazyStreamsSpec.groovy │ ├── MapFilterReduceSpec.groovy │ └── StreamsDemoTest.groovy ├── java ├── geocoder │ └── GeocoderTest.java ├── io │ └── JumbleJavaTest.java ├── sorting │ └── SortingDemoTest.java └── streams │ └── SumNumbersTest.java └── kotlin ├── astro └── AstroRequestTest.kt ├── extension └── PalindromeTest.kt ├── flickr └── FlickrGatewayTest.kt ├── functional ├── AlgorithmsKtTest.kt └── PrimesTest.kt ├── io └── JumbleKotlinTest.kt └── sequences └── SumNumbersTest.kt /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gradle 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "10:00" 8 | open-pull-requests-limit: 10 9 | ignore: 10 | - dependency-name: org.jetbrains.kotlin:kotlin-script-runtime 11 | versions: 12 | - 1.4.21-2 13 | - 1.4.30 14 | - 1.4.31 15 | - 1.5.0 16 | - dependency-name: org.jetbrains.kotlin.jvm 17 | versions: 18 | - 1.4.21-2 19 | - 1.4.30 20 | - 1.4.31 21 | - 1.4.32 22 | - 1.5.0 23 | - dependency-name: org.codehaus.groovy:groovy-all 24 | versions: 25 | - 3.0.7 26 | - dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-core 27 | versions: 28 | - 1.4.2-native-mt 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.jar 2 | .gradle 3 | build/ 4 | out/ 5 | 6 | .gradletasknamecache 7 | *.json 8 | 9 | .idea/ 10 | *.iml 11 | *.ipr 12 | 13 | pirate_key.txt 14 | yoda_key.txt 15 | 16 | .DS_Store 17 | 18 | -------------------------------------------------------------------------------- /Functional Programming in Java, Groovy, and Kotlin.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kousen/java_groovy_kotlin/1555cd25334b011cde4f76e2a9442bf52e3222e7/Functional Programming in Java, Groovy, and Kotlin.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Demo files for "Functional Programming with Java, Groovy, and Kotlin". 2 | 3 | Versions of this talk have been given as presentations at Oracle Code One (the conference formerly known as JavaOne), DevNexus, ApacheCon@Home, the JChampions Conference, and, most recently, at the ApacheCon North America conference in New Orleans, October 2022. 4 | -------------------------------------------------------------------------------- /antarctic_script.kts: -------------------------------------------------------------------------------- 1 | package scripts 2 | 3 | import java.time.Instant 4 | import java.time.ZoneId 5 | import java.time.ZonedDateTime 6 | 7 | val regex = """.*Antarctica.*""".toRegex() 8 | val instant: Instant = Instant.now() 9 | 10 | ZoneId.getAvailableZoneIds() 11 | .filter { regex.matches(it) } 12 | .map { instant.atZone(ZoneId.of(it)) } 13 | .sortedBy { it.offset.totalSeconds } 14 | .forEach { zdt -> 15 | println(String.format("%7s: %25s %7s", 16 | zdt.offset, zdt.zone, zdt.zone.rules.isDaylightSavings(instant))) 17 | } 18 | 19 | println() 20 | val southPole: ZonedDateTime = instant.atZone(ZoneId.of("Antarctica/South_Pole")) 21 | val dst = southPole.zone.rules.isDaylightSavings(Instant.now()) 22 | println("It is currently ${southPole.toLocalTime()} (UTC${southPole.offset}) at the South Pole") 23 | println("The South Pole ${if (dst) "is" else "is not"} on Daylight Savings Time") 24 | 25 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | // Without this suppression, version catalog usage here and in other build 2 | // files is marked red by IntelliJ: 3 | // https://youtrack.jetbrains.com/issue/KTIJ-19369. 4 | @Suppress("DSL_SCOPE_VIOLATION") 5 | plugins { 6 | java 7 | groovy 8 | alias(libs.plugins.kotlin.jvm) 9 | alias(libs.plugins.kotlin.serialization) 10 | alias(libs.plugins.versions) 11 | alias(libs.plugins.version.catalog.update) 12 | } 13 | 14 | java { 15 | toolchain { 16 | languageVersion.set(JavaLanguageVersion.of(17)) 17 | } 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | implementation(libs.groovy) 26 | implementation(libs.groovy.json) 27 | implementation(libs.groovy.swing) 28 | implementation(libs.gson) 29 | implementation(libs.kotlin.stdlib) 30 | implementation(libs.kotlin.coroutines) 31 | implementation(libs.kotlin.script.runtime) 32 | implementation(libs.kotlinx.converter) 33 | implementation(libs.retrofit.core) 34 | implementation(libs.retrofit.converter) 35 | 36 | testImplementation(libs.spock) 37 | testImplementation(libs.assertj) 38 | testImplementation(libs.bundles.junit) 39 | } 40 | 41 | tasks.test { 42 | useJUnitPlatform { 43 | maxParallelForks = Runtime.getRuntime().availableProcessors() / 2 + 1 44 | } 45 | } -------------------------------------------------------------------------------- /flickr_key.txt: -------------------------------------------------------------------------------- 1 | 70df4e6184f7e0e398a7e7acb59c8ce1 -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | assertj = "3.27.3" 3 | junit = "5.13.0" 4 | kotlin = "2.1.20" 5 | kotlinx-coroutines = "1.10.2" 6 | kotlinx-serialization = "1.8.1" 7 | groovy = "4.0.27" 8 | gson = "2.13.0" 9 | spock = "2.4-M5-groovy-4.0" 10 | retrofit = "2.11.0" 11 | retrofit-json = "1.8.1" 12 | retrofit-converter = "1.0.0" 13 | 14 | [libraries] 15 | assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } 16 | junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" } 17 | junit-vintage = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit" } 18 | kotlin-script-runtime = "org.jetbrains.kotlin:kotlin-script-runtime:2.1.20" 19 | kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } 20 | kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } 21 | kotlinx-converter = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" } 22 | groovy = { module = "org.apache.groovy:groovy", version.ref = "groovy" } 23 | groovy-json = { module = "org.apache.groovy:groovy-json", version.ref = "groovy" } 24 | groovy-swing = { module = "org.apache.groovy:groovy-swing", version.ref = "groovy" } 25 | gson = { module = "com.google.code.gson:gson", version.ref = "gson" } 26 | spock = { module = "org.spockframework:spock-core", version.ref = "spock" } 27 | retrofit-core = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" } 28 | retrofit-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "retrofit" } 29 | retrofit-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "retrofit-json" } 30 | retrofit-converter = { module = "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter", version.ref = "retrofit-converter" } 31 | 32 | [bundles] 33 | junit = [ 34 | "junit-jupiter", 35 | "junit-vintage", 36 | ] 37 | 38 | [plugins] 39 | kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } 40 | kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } 41 | version-catalog-update = "nl.littlerobots.version-catalog-update:1.0.0" 42 | versions = "com.github.ben-manes.versions:0.52.0" 43 | -------------------------------------------------------------------------------- /gradle/libs.versions.updates.toml: -------------------------------------------------------------------------------- 1 | # Version catalog updates generated at 2022-12-28T16:18:46.295766 2 | # 3 | # Contents of this file will be applied to libs.versions.toml when running versionCatalogApplyUpdates. 4 | # 5 | # Comments will not be applied to the version catalog when updating. 6 | # To prevent a version upgrade, comment out the entry or remove it. 7 | # 8 | [plugins] 9 | # From version 1.8.0-RC --> 1.8.0 10 | kotlin-jvm = "org.jetbrains.kotlin.jvm:1.8.0" 11 | # From version 1.8.0-RC --> 1.8.0 12 | kotlin-serialization = "org.jetbrains.kotlin.plugin.serialization:1.8.0" 13 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kousen/java_groovy_kotlin/1555cd25334b011cde4f76e2a9442bf52e3222e7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Feb 12 23:08:27 CST 2020 2 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip 3 | distributionBase=GRADLE_USER_HOME 4 | distributionPath=wrapper/dists 5 | zipStorePath=wrapper/dists 6 | zipStoreBase=GRADLE_USER_HOME 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=`expr $i + 1` 158 | done 159 | case $i in 160 | 0) set -- ;; 161 | 1) set -- "$args0" ;; 162 | 2) set -- "$args0" "$args1" ;; 163 | 3) set -- "$args0" "$args1" "$args2" ;; 164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=`save "$@"` 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | exec "$JAVACMD" "$@" 184 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("com.gradle.enterprise") version("3.8.1") 3 | } 4 | 5 | gradleEnterprise { 6 | buildScan { 7 | termsOfServiceUrl = "https://gradle.com/terms-of-service" 8 | termsOfServiceAgree = "yes" 9 | publishAlways() 10 | } 11 | } 12 | 13 | rootProject.name = "java_groovy_kotlin" 14 | -------------------------------------------------------------------------------- /src/main/groovy/collectors/adding_books_to_map.groovy: -------------------------------------------------------------------------------- 1 | package collectors 2 | 3 | List books = [ 4 | new Book(1, "Java 8 in Action"), 5 | new Book(2, "Java SE8 for the Really Impatient"), 6 | new Book(3, "Core Java Volume I -- Fundamentals"), 7 | new Book(4, "Functional Programming in Java"), 8 | new Book(5, "Making Java Groovy"), 9 | new Book(6, "Head First Java"), 10 | new Book(7, "Effective Java"), 11 | new Book(8, "Java 8 Pocket Guide"), 12 | new Book(9, "Gradle Recipes for Android"), 13 | new Book(10, "Spring Boot in Action") 14 | ] 15 | 16 | // Side-effects; works but not best approach 17 | //Map bookMap = [:] 18 | //books.each { b -> 19 | // bookMap[b.id] = b 20 | //} 21 | 22 | // Much better 23 | Map bookMap = books.inject([:]) { map, b -> 24 | map[b.id()] = b 25 | map 26 | } 27 | 28 | bookMap.each { println it } -------------------------------------------------------------------------------- /src/main/groovy/datetime/AntarcticaTimeZones.java: -------------------------------------------------------------------------------- 1 | package datetime; 2 | 3 | import java.time.LocalDateTime; 4 | import java.time.ZoneId; 5 | import java.util.Comparator; 6 | 7 | public class AntarcticaTimeZones { 8 | public static void main(String[] args) { 9 | LocalDateTime now = LocalDateTime.now(); 10 | ZoneId.getAvailableZoneIds() 11 | .stream() 12 | .filter(id -> id.contains("Antarctica")) 13 | .map(id -> now.atZone(ZoneId.of(id))) 14 | .sorted(Comparator.comparingInt(zoneId -> 15 | zoneId.getOffset().getTotalSeconds())) 16 | .forEach(zdt -> System.out.printf("%s: %s%n", zdt.getOffset(), zdt.getZone())); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/groovy/datetime/CTtoIndia.java: -------------------------------------------------------------------------------- 1 | package datetime; 2 | 3 | import java.time.LocalDate; 4 | import java.time.LocalTime; 5 | import java.time.ZoneId; 6 | import java.time.ZonedDateTime; 7 | import java.time.format.DateTimeFormatter; 8 | import java.util.stream.IntStream; 9 | 10 | public class CTtoIndia { 11 | public static void main(String[] args) { 12 | LocalDate localDate = LocalDate.now(); 13 | LocalTime localTime = LocalTime.MIDNIGHT; 14 | ZonedDateTime zdt = ZonedDateTime.of(localDate, localTime, 15 | ZoneId.of("America/New_York")); 16 | ZoneId india = ZoneId.of("Asia/Kolkata"); 17 | DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mma"); 18 | 19 | System.out.println("Connecticut India"); 20 | IntStream.rangeClosed(20, 30) // start at 8pm, incr by 1 hr 10 times 21 | .mapToObj(zdt::plusHours) 22 | .forEach(zonedDateTime -> System.out.printf(" %s %s%n", 23 | zonedDateTime.toLocalTime().format(formatter), 24 | zonedDateTime.withZoneSameInstant(india).toLocalTime())); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/groovy/datetime/FunnyOffsets.java: -------------------------------------------------------------------------------- 1 | package datetime; 2 | 3 | import java.time.Instant; 4 | import java.time.ZoneId; 5 | import java.time.ZoneOffset; 6 | import java.time.ZonedDateTime; 7 | import java.time.format.DateTimeFormatter; 8 | import java.time.format.FormatStyle; 9 | 10 | import static java.util.Comparator.comparingInt; 11 | 12 | /* 13 | * Alternative equivalent sorts: 14 | * .sorted((zoneId1, zoneId2) -> 15 | * (int) Duration.between(now.atZone(zoneId1), now.atZone(zoneId2)).getSeconds()) 16 | * -- or -- 17 | * .sorted((zoneId1, zoneId2) -> 18 | * (int) ChronoUnit.MINUTES.between(now.atZone(zoneId1), now.atZone(zoneId2)) 19 | */ 20 | public class FunnyOffsets { 21 | public static void main(String[] args) { 22 | Instant instant = Instant.now(); 23 | ZonedDateTime current = instant.atZone(ZoneId.systemDefault()); 24 | System.out.printf("Current time is %s%n%n", current); 25 | 26 | System.out.printf("%10s %20s %13s%n", "Offset", "ZoneId", "Time"); 27 | ZoneId.getAvailableZoneIds().stream() 28 | .map(ZoneId::of) 29 | .filter(zoneId -> { 30 | ZoneOffset offset = instant.atZone(zoneId).getOffset(); 31 | return offset.getTotalSeconds() % (60 * 60) != 0; 32 | }) 33 | .sorted(comparingInt(zoneId -> 34 | instant.atZone(zoneId).getOffset().getTotalSeconds())) 35 | .forEach(zoneId -> { 36 | ZonedDateTime zdt = current.withZoneSameInstant(zoneId); 37 | System.out.printf("%10s %25s %10s%n", zdt.getOffset(), zoneId, 38 | zdt.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT))); 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/groovy/datetime/antarctica.groovy: -------------------------------------------------------------------------------- 1 | package datetime 2 | 3 | import java.time.Instant 4 | import java.time.ZoneId 5 | 6 | ZoneId.availableZoneIds 7 | .findAll { it ==~ /.*Antarctica.*/ } 8 | .collect { Instant.now().atZone(ZoneId.of(it)) } 9 | .sort { it.offset.totalSeconds } 10 | .each { zdt -> println "$zdt.offset $zdt.zone" } -------------------------------------------------------------------------------- /src/main/groovy/datetime/ct_india.groovy: -------------------------------------------------------------------------------- 1 | package datetime 2 | 3 | import java.time.* 4 | import java.time.format.* 5 | 6 | LocalDate localDate = LocalDate.now() 7 | LocalTime localTime = LocalTime.MIDNIGHT 8 | ZonedDateTime zdt = ZonedDateTime.of(localDate, localTime, 9 | ZoneId.of('America/New_York')) 10 | ZoneId india = ZoneId.of('Asia/Kolkata') 11 | DateTimeFormatter dtf = DateTimeFormatter.ofPattern('hh:mma') 12 | println "Connecticut India" 13 | (20..30).each { 14 | ZonedDateTime shifted = zdt.plusHours(it) 15 | println " ${shifted.toLocalTime().format(dtf)} ${shifted.withZoneSameInstant(india).toLocalTime()}" 16 | } -------------------------------------------------------------------------------- /src/main/groovy/flickr/cat_pictures.groovy: -------------------------------------------------------------------------------- 1 | package flickr 2 | 3 | import groovy.json.JsonOutput 4 | import groovy.json.JsonSlurper 5 | import groovy.swing.SwingBuilder 6 | 7 | import javax.imageio.ImageIO 8 | import javax.swing.WindowConstants as WC 9 | import java.awt.* 10 | import java.util.List 11 | import java.util.stream.Collectors 12 | 13 | String endPoint = 'https://api.flickr.com/services/rest?' 14 | def params = 15 | [method : 'flickr.photos.search', 16 | api_key : new File('flickr_key.txt').text, 17 | format : 'json', 18 | tags : 'kitties', 19 | nojsoncallback: 1, 20 | media : 'photos', 21 | per_page : 6] 22 | 23 | // Build URL and download JSON data 24 | // NOTE: collect { it } on a map returns a list of key=value strings 25 | // because the toString method on Map.Entry returns key=value 26 | def queryString = params.collect { it }.join('&') 27 | String jsonTxt = "$endPoint$queryString".toURL().text 28 | 29 | // write formatted JSON data to file 30 | File f = new File('cats.json') 31 | if (f) f.delete() 32 | f << JsonOutput.prettyPrint(jsonTxt) 33 | println JsonOutput.prettyPrint(jsonTxt) 34 | 35 | // parse JSON data and extract photo elements 36 | def json = new JsonSlurper().parseText(jsonTxt) 37 | def photos = json.photos.photo 38 | 39 | // download images in parallel 40 | List images = photos.parallelStream() // Groovy using Java streams 41 | .map(this::photo2image) 42 | .collect(Collectors.toList()) 43 | 44 | // Convert a single photo JSON element into a java.awt.Image 45 | Image photo2image(p) { 46 | println "${Thread.currentThread().name}: ${p.title}" 47 | String url = "https://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg" 48 | ImageIO.read(url.toURL()) 49 | } 50 | 51 | // build UI using Swing 52 | new SwingBuilder().edt { 53 | frame(title: 'Cat pictures', visible: true, pack: true, 54 | layout: gridLayout(rows: 3, columns: 2), 55 | defaultCloseOperation: WC.EXIT_ON_CLOSE) { 56 | images.each { image -> 57 | label(icon: imageIcon(image: image)) 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/groovy/flickr/cats.json: -------------------------------------------------------------------------------- 1 | { 2 | "photos": { 3 | "page": 1, 4 | "pages": 25811, 5 | "perpage": 6, 6 | "total": 154866, 7 | "photo": [ 8 | { 9 | "id": "52564112139", 10 | "owner": "197025056@N06", 11 | "secret": "d711c3e8ff", 12 | "server": "65535", 13 | "farm": 66, 14 | "title": "Kitties", 15 | "ispublic": 1, 16 | "isfriend": 0, 17 | "isfamily": 0 18 | }, 19 | { 20 | "id": "52563398309", 21 | "owner": "124651729@N04", 22 | "secret": "cc22031770", 23 | "server": "65535", 24 | "farm": 66, 25 | "title": "Kiwi in a Box", 26 | "ispublic": 1, 27 | "isfriend": 0, 28 | "isfamily": 0 29 | }, 30 | { 31 | "id": "52558086167", 32 | "owner": "139664638@N02", 33 | "secret": "44584c5c79", 34 | "server": "65535", 35 | "farm": 66, 36 | "title": "Candyland", 37 | "ispublic": 1, 38 | "isfriend": 0, 39 | "isfamily": 0 40 | }, 41 | { 42 | "id": "52557714022", 43 | "owner": "67906779@N00", 44 | "secret": "6efa807f0b", 45 | "server": "65535", 46 | "farm": 66, 47 | "title": "Miracle on 34th St.", 48 | "ispublic": 1, 49 | "isfriend": 0, 50 | "isfamily": 0 51 | }, 52 | { 53 | "id": "52552545332", 54 | "owner": "187429293@N05", 55 | "secret": "2780667efe", 56 | "server": "65535", 57 | "farm": 66, 58 | "title": "Winter cats", 59 | "ispublic": 1, 60 | "isfriend": 0, 61 | "isfamily": 0 62 | }, 63 | { 64 | "id": "52548409322", 65 | "owner": "196183266@N03", 66 | "secret": "e85a332efb", 67 | "server": "65535", 68 | "farm": 66, 69 | "title": "Lilac Bicolor Van Exotic Longhair Kitten", 70 | "ispublic": 1, 71 | "isfriend": 0, 72 | "isfamily": 0 73 | } 74 | ] 75 | }, 76 | "stat": "ok" 77 | } -------------------------------------------------------------------------------- /src/main/groovy/flickr/flickr_key.txt: -------------------------------------------------------------------------------- 1 | 70df4e6184f7e0e398a7e7acb59c8ce1 -------------------------------------------------------------------------------- /src/main/groovy/functional/annotations/AnnotatedFunctions.groovy: -------------------------------------------------------------------------------- 1 | package functional.annotations 2 | 3 | import groovy.transform.Memoized 4 | import groovy.transform.TailRecursive 5 | 6 | class AnnotatedFunctions { 7 | @Memoized 8 | BigInteger fib(BigInteger n) { 9 | if (n == 0) 0 10 | else if (n == 1) 1 11 | else fib(n - 1) + fib(n - 2) 12 | } 13 | 14 | @Memoized 15 | BigInteger fact(BigInteger n) { 16 | n < 2 ? 1 : n * fact(n - 1) 17 | } 18 | 19 | @Memoized 20 | long add(long x, long y) { 21 | sleep(1000) 22 | x + y 23 | } 24 | 25 | @TailRecursive 26 | BigInteger factorial(BigInteger n, BigInteger acc = 1G) { 27 | n < 2 ? acc : factorial(n - 1G, n * acc) 28 | } 29 | 30 | @TailRecursive 31 | int gcd(int x, int y) { 32 | if (y == 0) { 33 | return x 34 | } else { 35 | return gcd(y, x % y) 36 | } 37 | } 38 | 39 | @TailRecursive 40 | long sumUp(long number, long sum = 0) { 41 | if (number == 0) 42 | return sum 43 | sumUp(number - 1, sum + number) 44 | } 45 | 46 | @TailRecursive 47 | long sizeOfList(list, counter = 0) { 48 | if (list.size() == 0) { 49 | counter 50 | } else { 51 | sizeOfList(list.tail(), counter + 1) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/groovy/functional/annotations/UseAnnotatedFunctions.java: -------------------------------------------------------------------------------- 1 | package functional.annotations; 2 | 3 | import java.math.BigInteger; 4 | import java.util.stream.IntStream; 5 | 6 | public class UseAnnotatedFunctions { 7 | private final AnnotatedFunctions mf = new AnnotatedFunctions(); 8 | 9 | public void timings() { 10 | IntStream.range(1, 100) 11 | .forEach(i -> { 12 | long before = System.nanoTime(); 13 | BigInteger val = mf.fib(new BigInteger(i + "")); 14 | long after = System.nanoTime(); 15 | System.out.printf("%3d: %8s, fib(%2d) = %d%n", i, (after - before) / 1e9, i, val); 16 | }); 17 | 18 | 19 | System.out.println(mf.add(3, 5)); 20 | System.out.println(mf.add(3, 5)); 21 | System.out.println(mf.add(3, 5)); 22 | 23 | IntStream.range(1, 100) 24 | .forEach(i -> { 25 | long before = System.nanoTime(); 26 | BigInteger val = mf.fact(new BigInteger(i + "")); 27 | long after = System.nanoTime(); 28 | System.out.printf("%3d: %8s, fact(%2d) = %d%n", i, (after - before) / 1e9, i, val); 29 | }); 30 | 31 | System.out.println("70000! has " + 32 | mf.factorial(new BigInteger(70_000 + "")).toString().length() + 33 | " digits"); 34 | } 35 | 36 | public static void main(String[] args) { 37 | UseAnnotatedFunctions uf = new UseAnnotatedFunctions(); 38 | uf.timings(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/groovy/functional/annotations/memoize.groovy: -------------------------------------------------------------------------------- 1 | package functional.annotations 2 | 3 | import groovy.transform.Memoized 4 | 5 | Closure add = { x, y -> sleep 1000; x + y }.memoize() 6 | 7 | println add(3, 4) // takes 1 sec 8 | println add(3, 4) // immediate 9 | println add('a', 'b') // takes 1 sec 10 | println add('a', 'b') // immediate 11 | 12 | def fib = { n -> 13 | if (n < 2) 1 14 | else call(n - 1) + call(n - 2) 15 | }.memoize() 16 | 17 | println fib(10) 18 | 19 | @Memoized 20 | long fib1(long n) { 21 | if (n < 2) 1 22 | else fib1(n - 1) + fib1(n - 2) 23 | } 24 | 25 | println fib1(100) -------------------------------------------------------------------------------- /src/main/groovy/functional/annotations/tail_recursive.groovy: -------------------------------------------------------------------------------- 1 | package functional.annotations 2 | 3 | import groovy.transform.TailRecursive 4 | 5 | import static java.math.BigInteger.ONE 6 | 7 | @TailRecursive 8 | def fact(n, acc = ONE) { 9 | n < 2 ? acc : fact(n - ONE, n * acc) 10 | } 11 | 12 | def result = fact(70000) 13 | assert "$result".size() == 308_760 -------------------------------------------------------------------------------- /src/main/groovy/functional/annotations/trampoline.groovy: -------------------------------------------------------------------------------- 1 | package functional.annotations 2 | 3 | def fact 4 | fact = { n, total -> 5 | n == 0 ? total : fact.trampoline(n - 1, n * total) 6 | }.trampoline() 7 | def factorial = { n -> fact(n, 1G) } 8 | println factorial(20) // => 2432902008176640000 9 | 10 | def fib 11 | fib = { n, a = BigInteger.ZERO, b = BigInteger.ONE -> 12 | n == 0 ? a : fib.trampoline(n - 1, b, a + b) 13 | }.trampoline() 14 | 15 | def result = fib(1001) 16 | println "$result".size() // 209 digits -------------------------------------------------------------------------------- /src/main/groovy/functional/executable_class.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | class Discount { 4 | def percentage 5 | 6 | def call(amount) { 7 | percentage * amount 8 | } 9 | } 10 | 11 | Discount disc = new Discount(percentage: 0.1) 12 | assert disc(1000) == 100 13 | 14 | disc.percentage = 0.15 15 | assert disc(1000) == 150 -------------------------------------------------------------------------------- /src/main/groovy/functional/immutables/Point.groovy: -------------------------------------------------------------------------------- 1 | package functional.immutables 2 | 3 | import groovy.transform.Immutable 4 | 5 | @Immutable 6 | class Point { 7 | double x 8 | double y 9 | 10 | static Point createPoint(double x, double y) { 11 | new Point(x, y) 12 | } 13 | 14 | Point translate(double dx = 0, double dy = 0) { 15 | new Point(x + dx, y + dy) 16 | } 17 | 18 | Point rotate(double radians) { 19 | double r = Math.sqrt(x * x + y + y) 20 | new Point(r * Math.cos(radians), r * Math.sin(radians)) 21 | } 22 | 23 | Point plus(Point p) { 24 | new Point(x + p.x, y + p.y) 25 | } 26 | 27 | Point minus(Point p) { 28 | new Point(x - p.x, y - p.y) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/groovy/functional/immutables/UsePoint.java: -------------------------------------------------------------------------------- 1 | package functional.immutables; 2 | 3 | public class UsePoint { 4 | public static void main(String[] args) { 5 | Point p = Point.createPoint(1, 0); 6 | System.out.println(p); 7 | System.out.printf("(%s,%s)%n", p.getX(), p.getY()); 8 | 9 | Point p1 = p.translate(2, 3); 10 | System.out.println(p1); // should be (3,3) 11 | 12 | Point p2 = p.rotate(Math.PI / 2); 13 | System.out.println(p2); // should be (0,1) 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/main/groovy/functional/map_filter_reduce.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | def nums = [3, 1, 4, 1, 5, 9, 2, 6, 5] 4 | 5 | int total = nums 6 | .findAll { it % 3 == 0 } 7 | .collect { it * 2 } 8 | .inject(0) { acc, val -> acc + val } 9 | 10 | assert total == 36 11 | 12 | // or simply 13 | total = nums 14 | .findAll { it % 3 == 0 } 15 | .collect { it * 2 } 16 | .sum() 17 | 18 | assert total == 36 19 | 20 | total = 0 21 | nums.each { total += it } -------------------------------------------------------------------------------- /src/main/groovy/functional/using_inject.groovy: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | List nums = [3, 1, 4, 1, 5, 9, 2, 6, 5] 4 | assert nums.sum() == 5 | nums.inject { acc, val -> 6 | acc + val 7 | } 8 | 9 | List strings = 'this is a list of strings'.split() 10 | List sorted = strings.sort(false) 11 | println sorted 12 | sorted.inject { prev, curr -> 13 | assert prev <= curr 14 | curr 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/main/groovy/geocoder/Geocoder.groovy: -------------------------------------------------------------------------------- 1 | package geocoder 2 | 3 | import groovy.json.JsonSlurper 4 | 5 | class Geocoder { 6 | public static final String BASE = 7 | 'https://maps.googleapis.com/maps/api/geocode/json?' 8 | private static final String KEY = 9 | 'AIzaSyDw_d6dfxDEI7MAvqfGXEIsEMwjC1PWRno' 10 | 11 | void fillInLatLng(Location location) { 12 | String encoded = [location.street, location.city, location.state].collect { 13 | URLEncoder.encode(it, 'UTF-8') 14 | }.join(',') 15 | String qs = "address=$encoded&key=$KEY" 16 | def root = new JsonSlurper().parse("$BASE$qs".toURL()) 17 | def loc = root.results[0].geometry.location 18 | location.latitude = loc.lat.toBigDecimal() 19 | location.longitude = loc.lng.toBigDecimal() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/groovy/geocoder/Location.java: -------------------------------------------------------------------------------- 1 | package geocoder; 2 | 3 | import java.util.Objects; 4 | 5 | public class Location { 6 | private String street; 7 | private String city; 8 | private String state; 9 | 10 | private double latitude; 11 | private double longitude; 12 | 13 | public Location() {} 14 | 15 | public Location(String street, String city, String state) { 16 | this.street = street; 17 | this.city = city; 18 | this.state = state; 19 | } 20 | 21 | public String getStreet() { 22 | return street; 23 | } 24 | 25 | public void setStreet(String street) { 26 | this.street = street; 27 | } 28 | 29 | public String getCity() { 30 | return city; 31 | } 32 | 33 | public void setCity(String city) { 34 | this.city = city; 35 | } 36 | 37 | public String getState() { 38 | return state; 39 | } 40 | 41 | public void setState(String state) { 42 | this.state = state; 43 | } 44 | 45 | public double getLatitude() { 46 | return latitude; 47 | } 48 | 49 | public void setLatitude(double latitude) { 50 | this.latitude = latitude; 51 | } 52 | 53 | public double getLongitude() { 54 | return longitude; 55 | } 56 | 57 | public void setLongitude(double longitude) { 58 | this.longitude = longitude; 59 | } 60 | 61 | public String toString() { 62 | return String.format("%s, %s, %s(%s,%s)", 63 | street, city, state, latitude, longitude); 64 | } 65 | 66 | @Override 67 | public boolean equals(Object o) { 68 | if (this == o) return true; 69 | if (!(o instanceof Location location)) return false; 70 | 71 | if (!Objects.equals(street, location.street)) return false; 72 | if (!city.equals(location.city)) return false; 73 | return state.equals(location.state); 74 | 75 | } 76 | 77 | @Override 78 | public int hashCode() { 79 | int result = street != null ? street.hashCode() : 0; 80 | result = 31 * result + city.hashCode(); 81 | result = 31 * result + state.hashCode(); 82 | return result; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/groovy/io/Jumble.groovy: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | import groovy.transform.CompileStatic 4 | 5 | @CompileStatic 6 | class Jumble1 { 7 | private List wordList = 8 | new File('src/main/resources/dict/words').readLines() 9 | .findAll { it.size() == 5 || it.size() == 6 } 10 | 11 | List solve(String clue) { 12 | List letters = clue.split('').toList() 13 | letters.permutations() 14 | .collect { it.join('') } 15 | .findAll { wordList.contains(it) } 16 | } 17 | } 18 | 19 | @CompileStatic 20 | class Jumble2 { 21 | private Map> wordMap = 22 | new File('src/main/resources/dict/words').readLines() 23 | .findAll { it.size() == 5 || it.size() == 6 } 24 | .groupBy(this.&word2key) as Map> 25 | 26 | private static String word2key(String word) { 27 | word.toList().sort().join('') 28 | } 29 | 30 | List solve(String clue) { 31 | wordMap[word2key(clue)] 32 | } 33 | } 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/main/groovy/lambdas/PrimeCheckerGroovy.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | class PrimeCheckerGroovy { 4 | 5 | boolean isPrime(int x) { 6 | if (x < 2) throw new IllegalArgumentException("x must be >= 2") 7 | 8 | int limit = (int) Math.sqrt(x) + 1 9 | x == 2 || !(2..limit).find { n -> x % n == 0 } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/groovy/lambdas/closures.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | import java.time.LocalDate 4 | 5 | // Define a closure 6 | Closure add = { x, y -> x + y } 7 | 8 | assert add.call(3, 4) == 7 9 | assert add(3, 4) == 7 10 | assert add('abc', 'def') == 'abcdef' 11 | 12 | LocalDate now = LocalDate.now() 13 | LocalDate then = add(now, 3) // same as now + 3 14 | assert then - now == 3 15 | 16 | // Define a closure with a variable number of untyped args 17 | def addAll = { ... values -> values.sum() } 18 | 19 | assert addAll(1, 2, 3) == 6 20 | assert addAll('a', 'b') == 'ab' 21 | 22 | // Default args 23 | def mult = { x, y = 2 -> x * y } 24 | 25 | assert mult(3, 4) == 12 26 | assert mult(3) == 6 27 | 28 | // Curry 29 | def add3 = add.curry(3) 30 | assert add3(4) == 7 31 | 32 | def times2 = mult.rcurry(2) 33 | assert times2(4) == 8 34 | assert times2('abc') == 'abcabc' -------------------------------------------------------------------------------- /src/main/groovy/lambdas/composition.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | def add3 = { it + 3 } 4 | def times2 = { it * 2 } 5 | 6 | def times2add3 = add3 << times2 7 | assert 13 == times2add3(5) 8 | assert 13 == add3(times2(5)) 9 | assert 13 == (times2 >> add3)(5) // reverse composition 10 | 11 | def add3times2 = times2 << add3 12 | assert 16 == add3times2(5) 13 | assert 16 == times2(add3(5)) 14 | -------------------------------------------------------------------------------- /src/main/groovy/lambdas/currying.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | Closure add = { x,y -> x + y } 4 | 5 | assert 7 == add.call(3, 4) 6 | assert 7 == add(3,4) 7 | assert 'abcdef' == add('abc', 'def') 8 | 9 | Closure add3 = add.curry(3) 10 | 11 | assert 7 == add3(4) 12 | assert 0 == add3(-3) 13 | 14 | -------------------------------------------------------------------------------- /src/main/groovy/lambdas/lambdas.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | import java.util.stream.DoubleStream 4 | 5 | [3, 1, 4, 1, 5, 9].stream() 6 | .map { it * 2 } 7 | .filter { it % 3 == 0 } 8 | .forEach { println it } 9 | 10 | println DoubleStream.generate(Math::random) 11 | .limit(1000) 12 | .mapToInt { (int) (it * 100) } 13 | .filter { it % 3 == 0 } 14 | .summaryStatistics() -------------------------------------------------------------------------------- /src/main/groovy/lambdas/map_filter_reduce.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | List nums = [3, 1, 4, 1, 5, 9, 2, 6, 5] 4 | 5 | assert 36 == nums.collect { it * 2 } // map 6 | .findAll { it % 3 == 0 } // filter 7 | .sum() // reduce 8 | 9 | List cities = ['Boston', 'New York', 'London', 'Hyderabad'] 10 | 11 | assert cities.collect { String s -> s.toUpperCase() } 12 | .sort(false) 13 | .join(', ') == 'BOSTON, HYDERABAD, LONDON, NEW YORK' 14 | 15 | println cities.collect { it.toUpperCase() } 16 | .sort { it.size() } 17 | .join(', ') 18 | 19 | -------------------------------------------------------------------------------- /src/main/groovy/lambdas/method_references.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | List cart = [] 4 | 5 | def addToCart = cart.&add 6 | // addToCart = cart::add // okay as of Groovy 3.0 7 | def removeFromCart = cart.&remove 8 | 9 | addToCart 'milk' 10 | addToCart 'butter' 11 | addToCart 'eggs' 12 | addToCart 'double chocolate fudge' 13 | removeFromCart 'double chocolate fudge' 14 | 15 | println cart 16 | -------------------------------------------------------------------------------- /src/main/groovy/metaprogramming/pirate.groovy: -------------------------------------------------------------------------------- 1 | //file:noinspection GroovyAssignabilityCheck 2 | package metaprogramming 3 | 4 | import groovy.json.JsonSlurper 5 | 6 | String.metaClass.pirate = { -> 7 | String key = new File('pirate_key.txt').text 8 | String base = 'http://api.funtranslations.com/translate/pirate.json?' 9 | String qs = "text=${URLEncoder.encode(delegate, 'UTF-8')}&api_key=$key" 10 | String txt = "$base$qs".toURL().text 11 | def json = new JsonSlurper().parseText(txt) 12 | json.contents.translated 13 | } 14 | 15 | println "Hello, World!".pirate() 16 | println "How are you today?".pirate() 17 | println "Please fill out your session evals".pirate() 18 | println "I'd like to add you to my professional network on LinkedIn".pirate() -------------------------------------------------------------------------------- /src/main/groovy/metaprogramming/pirate_key.txt: -------------------------------------------------------------------------------- 1 | U9kEKw_ZYOoe2w_9ELm5OQeF -------------------------------------------------------------------------------- /src/main/groovy/sorting/GolfersCS.groovy: -------------------------------------------------------------------------------- 1 | package sorting 2 | 3 | import groovy.transform.* 4 | 5 | // Caddyshack golfers 6 | 7 | @Sortable(includes = ['height', 'score', 'last', 'first']) 8 | class GolferCS { 9 | String first 10 | String last 11 | int score 12 | int height 13 | 14 | void setHeight(int height) { this.height = -height } 15 | 16 | String toString() { "$score: $last, $first (${height.abs()})" } 17 | } 18 | 19 | def golfers = [ 20 | new GolferCS(height: 70, score: 68, last: 'Nicklaus', first: 'Jack'), 21 | new GolferCS(height: 73, score: 70, last: 'Woods', first: 'Tiger'), 22 | new GolferCS(height: 69, score: 70, last: 'Watson', first: 'Tom'), 23 | new GolferCS(height: 76, score: 68, last: 'Webb', first: 'Ty'), 24 | new GolferCS(height: 75, score: 70, last: 'Watson', first: 'Bubba')] 25 | 26 | golfers.sort().each { println it } -------------------------------------------------------------------------------- /src/main/groovy/sorting/GroovyGolfer.groovy: -------------------------------------------------------------------------------- 1 | package sorting 2 | 3 | import groovy.transform.Sortable 4 | 5 | @Sortable(includes = ['score', 'last', 'first']) 6 | class GroovyGolfer { 7 | String first 8 | String last 9 | int score 10 | 11 | String toString() { "$score: $last, $first" } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/groovy/sorting/SortingDemoGroovy.groovy: -------------------------------------------------------------------------------- 1 | package sorting 2 | 3 | class SortingDemoGroovy { 4 | List strings = 'this is a list of strings'.split() 5 | 6 | // Default sort 7 | List defaultSort() { 8 | strings.sort() 9 | } 10 | 11 | // Length sort with 2-arg closure 12 | List lengthSortWithTwoArgClosure() { 13 | strings.sort { s1, s2 -> s1.size() <=> s2.size() } 14 | } 15 | 16 | List lengthSortWithOneArgClosure() { 17 | strings.sort { it.size() } 18 | } 19 | 20 | List lengthSortThenAlphaSort() { 21 | strings.sort { s1, s2 -> 22 | s1.size() <=> s2.size() ?: s1 <=> s2 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/groovy/sorting/sort_groovy_golfers.groovy: -------------------------------------------------------------------------------- 1 | package sorting 2 | 3 | def golfers = [ 4 | new GroovyGolfer(score: 68, last: 'Nicklaus', first: 'Jack'), 5 | new GroovyGolfer(score: 70, last: 'Woods', first: 'Tiger'), 6 | new GroovyGolfer(score: 70, last: 'Watson', first: 'Tom'), 7 | new GroovyGolfer(score: 68, last: 'Webb', first: 'Ty'), 8 | new GroovyGolfer(score: 70, last: 'Watson', first: 'Bubba')] 9 | 10 | List sorted = golfers.toSorted() 11 | 12 | assert sorted.first().score == 68 13 | assert sorted.first().last == 'Nicklaus' 14 | assert sorted.last().first == 'Tiger' 15 | 16 | // print the scoreboard 17 | sorted.each { println it } 18 | // sorted.forEach(System.out.&println) 19 | 20 | // print the last names in sorted order 21 | println sorted.last 22 | 23 | // sort by last name only 24 | println golfers.sort(false) { it.last } -------------------------------------------------------------------------------- /src/main/groovy/streams/LazyStreamsGroovy.groovy: -------------------------------------------------------------------------------- 1 | package streams 2 | 3 | import java.util.stream.IntStream 4 | 5 | class LazyStreamsGroovy { 6 | int firstEvenDivBy3() { 7 | (100..<200).collect { it * 2 } 8 | .find { it % 3 == 0 } 9 | } 10 | 11 | int firstEvenDivBy3Verbose() { 12 | (100..<200).collect { println it; it * 2 } 13 | .find { println it; it % 3 == 0 } 14 | } 15 | 16 | int firstEvenDivBy3UsingStreams() { 17 | IntStream.rangeClosed(100, 200) 18 | .filter { println it; it % 3 == 0 } 19 | .map { println it; it * 2 } 20 | .findFirst().orElse(0) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/groovy/streams/StreamsDemo.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import java.math.BigDecimal; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | import java.util.Random; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.Stream; 9 | 10 | @SuppressWarnings("unused") 11 | public class StreamsDemo { 12 | private final List strings = Arrays.asList("this", "is", "a", 13 | "list", "of", "strings"); 14 | 15 | public String joinStream() { 16 | return String.join(" ", strings); 17 | } 18 | 19 | public String joinUpperCase() { 20 | // convert the strings to upper case and join them using a single space 21 | return strings.stream() 22 | .map(String::toUpperCase) 23 | .collect(Collectors.joining(" ")); 24 | } 25 | 26 | public int getTotalLength() { 27 | // map the individual strings to ints and sum them 28 | return strings.stream() 29 | .mapToInt(String::length) 30 | .sum(); 31 | } 32 | 33 | public double sumFirstNBigDecimals(int num) { 34 | // use the iterate method on stream, starting from BigDecimal.ONE, 35 | // adding BigDecimal.ONE each time 36 | // use the limit method to produce only "num" values 37 | // use mapToDouble to convert the BigDecimal instances to doubles 38 | // use the sum method on DoubleStream to add them up 39 | return Stream.iterate(BigDecimal.ONE, bd -> bd.add(BigDecimal.ONE)) 40 | .limit(num) 41 | .mapToDouble(BigDecimal::doubleValue) 42 | .sum(); 43 | } 44 | 45 | public Double sumRandoms1(int num) { 46 | return Stream.generate(Math::random) 47 | .limit(num) 48 | .reduce(Double::sum).orElse(0.0); 49 | } 50 | 51 | public Double sumRandoms2(int num) { 52 | return Stream.generate(Math::random) 53 | .limit(num) 54 | .reduce((acc, n) -> { 55 | System.out.printf("Acc=%s, n=%s%n", acc, n); 56 | return acc + n; 57 | }) 58 | .orElse(0.0); 59 | } 60 | 61 | public Double sumRandoms3(int num) { 62 | Random r = new Random(); 63 | return r.doubles() 64 | .limit(num) 65 | .sum(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/collectors/AddCollectionToMap.java: -------------------------------------------------------------------------------- 1 | package collectors; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.function.Function; 8 | import java.util.stream.Collectors; 9 | 10 | public class AddCollectionToMap { 11 | 12 | private static void printMap(Map map) { 13 | map.forEach((k, v) -> System.out.printf("%s: %s%n", k, v)); 14 | } 15 | 16 | public static void main(String[] args) { 17 | List books = Arrays.asList( 18 | new Book(1, "Java 8 in Action"), 19 | new Book(2, "Java SE8 for the Really Impatient"), 20 | new Book(3, "Core Java Volume I -- Fundamentals"), 21 | new Book(4, "Functional Programming in Java"), 22 | new Book(5, "Making Java Groovy"), 23 | new Book(6, "Head First Java"), 24 | new Book(7, "Effective Java"), 25 | new Book(8, "Java 8 Pocket Guide"), 26 | new Book(9, "Gradle Recipes for Android"), 27 | new Book(10, "Spring Boot in Action") 28 | ); 29 | 30 | // Option 1: explicit identity lambda 31 | Map bookMap = books.stream() 32 | .collect(Collectors.toMap(Book::id, b -> b)); 33 | 34 | printMap(bookMap); 35 | 36 | // Option 2: Function.identity method 37 | bookMap = books.stream() 38 | .collect(Collectors.toMap(Book::id, Function.identity())); 39 | 40 | printMap(bookMap); 41 | 42 | // Option 3: reduce(U identity, 43 | // BiFunction accumulator, 44 | // BinaryOperator combiner) 45 | bookMap = books.stream() 46 | .reduce(new HashMap<>(), // init accumulator with map 47 | (map, book) -> { // add a book to the map 48 | map.put(book.id(), book); 49 | return map; 50 | }, 51 | (m1, m2) -> { // combine maps 52 | m1.putAll(m2); 53 | return m1; 54 | }); 55 | 56 | printMap(bookMap); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/collectors/Book.java: -------------------------------------------------------------------------------- 1 | package collectors; 2 | 3 | public record Book(int id, String name) {} 4 | -------------------------------------------------------------------------------- /src/main/java/composition/CombineLambdas.java: -------------------------------------------------------------------------------- 1 | package composition; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.function.Consumer; 7 | import java.util.function.Predicate; 8 | import java.util.logging.Logger; 9 | 10 | public class CombineLambdas { 11 | public static void main(String[] args) { 12 | Logger log = Logger.getLogger("Logger"); 13 | 14 | List stringsWithNulls = Arrays.asList("this", null, 15 | "is", null, null, "a", "list", null, "with", "nulls"); 16 | 17 | Predicate nullFilter = Objects::nonNull; 18 | Predicate evens = s -> s.length() % 2 == 0; 19 | 20 | Consumer logger = log::info; 21 | Consumer printer = System.out::println; 22 | 23 | stringsWithNulls.stream() 24 | .filter(nullFilter.and(evens)) 25 | .forEach(logger.andThen(printer)); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/JumbleJava.java: -------------------------------------------------------------------------------- 1 | package io; 2 | 3 | import java.io.IOException; 4 | import java.io.UncheckedIOException; 5 | import java.nio.file.Files; 6 | import java.nio.file.Paths; 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.stream.Collectors; 12 | 13 | public class JumbleJava { 14 | private final Map> wordMap; 15 | 16 | public JumbleJava() { 17 | try (var map = 18 | Files.lines(Paths.get("src/main/resources/dict/words"))) { 19 | wordMap = map.filter(word -> word.length() == 5 || word.length() == 6) 20 | .collect(Collectors.groupingBy(this::word2key)); 21 | } catch (IOException e) { 22 | throw new UncheckedIOException(e); 23 | } 24 | } 25 | 26 | public List solve(String clue) { 27 | return wordMap.getOrDefault(word2key(clue), Collections.singletonList("")); 28 | } 29 | 30 | private String word2key(String word) { 31 | return Arrays.stream(word.split("")) 32 | .sorted() 33 | .collect(Collectors.joining()); 34 | } 35 | 36 | public List> parallelSolve(String... clues) { 37 | return Arrays.stream(clues) 38 | .parallel() 39 | .map(this::solve) 40 | .collect(Collectors.toList()); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/lambdas/LambdaDemo.java: -------------------------------------------------------------------------------- 1 | package lambdas; 2 | 3 | import java.util.List; 4 | import java.util.function.Consumer; 5 | 6 | //@SuppressWarnings("Convert2MethodRef") 7 | public class LambdaDemo { 8 | @SuppressWarnings("Convert2Lambda") 9 | public static void main(String[] args) { 10 | List strings = List.of("this", "is", "a", "list", "of", "strings"); 11 | 12 | // Anonymous inner class impl of Consumer 13 | strings.forEach(new Consumer<>() { 14 | @Override 15 | public void accept(String s) { 16 | System.out.println("The string is " + s); 17 | } 18 | }); 19 | 20 | // Use a simple expression lambda for Consumer that prints each value 21 | strings.forEach(s -> System.out.println("The string is " + s)); 22 | 23 | // Use the full block form of the lambda 24 | //noinspection CodeBlock2Expr 25 | strings.forEach(s -> { 26 | System.out.println("The string is " + s); 27 | }); 28 | 29 | // Use a method reference to print each value 30 | // strings.forEach( /* method reference for println */ ); 31 | 32 | // Assign lambda to variable 33 | // Consumer printer = // lambda or method reference 34 | // strings.forEach(printer); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/lambdas/PrimeChecker.java: -------------------------------------------------------------------------------- 1 | package lambdas; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | public class PrimeChecker { 6 | 7 | public boolean isPrimeJava7(int x) { 8 | if (x < 2) throw new IllegalArgumentException("x must be >= 2"); 9 | if (x == 2) return true; 10 | int limit = (int) Math.sqrt(x) + 1; 11 | 12 | for (int i = 2; i <= limit; i++) { 13 | if (x % i == 0) { 14 | return false; 15 | } 16 | } 17 | return true; 18 | } 19 | 20 | public boolean isPrime(int x) { 21 | if (x < 2) throw new IllegalArgumentException("x must be >= 2"); 22 | int limit = (int) Math.sqrt(x) + 1; 23 | 24 | return x == 2 || IntStream.rangeClosed(2, limit) 25 | .noneMatch(n -> x % n == 0); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/sorting/Golfer.java: -------------------------------------------------------------------------------- 1 | package sorting; 2 | 3 | public record Golfer(String first, String last, int score) implements Comparable { 4 | public int compareTo(Golfer other) { 5 | return Integer.compare(score, other.score); 6 | } 7 | } -------------------------------------------------------------------------------- /src/main/java/sorting/SortGolfers.java: -------------------------------------------------------------------------------- 1 | package sorting; 2 | 3 | import java.util.Arrays; 4 | import java.util.Comparator; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.stream.Collectors; 8 | 9 | @SuppressWarnings("unused") 10 | public class SortGolfers { 11 | private final List golfers = Arrays.asList( 12 | new Golfer("Jack", "Nicklaus", 68), 13 | new Golfer("Tiger", "Woods", 70), 14 | new Golfer("Tom", "Watson", 70), 15 | new Golfer("Ty", "Webb", 68), 16 | new Golfer("Bubba", "Watson", 70) 17 | ); 18 | 19 | // default sort is by score 20 | public void defaultSort() { 21 | golfers.stream() 22 | .sorted() 23 | .forEach(System.out::println); 24 | } 25 | 26 | // sort by score, then by last name 27 | public void sortByScoreThenLast() { 28 | golfers.stream() 29 | .sorted(Comparator.comparingInt(Golfer::score) 30 | .thenComparing(Golfer::last)) 31 | .forEach(System.out::println); 32 | } 33 | 34 | // sort by score, then by last, then by first 35 | public void sortByScoreThenLastThenFirst() { 36 | golfers.stream() 37 | .sorted(Comparator.comparingInt(Golfer::score) 38 | .thenComparing(Golfer::last) 39 | .thenComparing(Golfer::first)) 40 | .forEach(System.out::println); 41 | } 42 | 43 | public void partitionByScore() { 44 | Map> map = golfers.stream() 45 | .collect(Collectors.partitioningBy( 46 | golfer -> golfer.score() < 70)); 47 | 48 | map.forEach((k,v) -> { 49 | System.out.println(k); 50 | v.forEach(System.out::println); 51 | }); 52 | } 53 | 54 | public void groupByScore() { 55 | Map> map = golfers.stream() 56 | .collect(Collectors.groupingBy(Golfer::score)); 57 | 58 | map.forEach((k,v) -> { 59 | System.out.println(k); 60 | v.forEach(System.out::println); 61 | }); 62 | } 63 | 64 | public static void main(String[] args) { 65 | SortGolfers sg = new SortGolfers(); 66 | // sg.defaultSort(); 67 | // sg.sortByScoreThenLast(); 68 | sg.sortByScoreThenLastThenFirst(); 69 | // sg.partitionByScore(); 70 | // sg.groupByScore(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/sorting/SortingDemo.java: -------------------------------------------------------------------------------- 1 | package sorting; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.Comparator; 6 | import java.util.List; 7 | 8 | import static java.util.Comparator.*; 9 | import static java.util.stream.Collectors.toList; 10 | 11 | public class SortingDemo { 12 | private final List sampleStrings = 13 | Arrays.asList("this", "is", "a", "list", "of", "strings"); 14 | 15 | // Default sort from Java 7- 16 | public List alphaSort() { 17 | Collections.sort(sampleStrings); 18 | return sampleStrings; 19 | } 20 | 21 | // Default sort from Java 8+ 22 | public List alphaSortUsingStreams() { 23 | return sampleStrings.stream() 24 | .sorted() 25 | .collect(toList()); 26 | } 27 | 28 | // Java 7- using Comparator with anonymous inner class 29 | @SuppressWarnings("Convert2Lambda") 30 | public List lengthReverseSortWithComparator() { 31 | sampleStrings.sort(new Comparator<>() { 32 | @Override 33 | public int compare(String s1, String s2) { 34 | return s2.length() - s1.length(); 35 | } 36 | }); 37 | return sampleStrings; 38 | } 39 | 40 | // Using a lambda as a Comparator with a lambda 41 | @SuppressWarnings("ComparatorCombinators") 42 | public List lengthSortWithLambda() { 43 | sampleStrings.sort((s1, s2) -> s1.length() - s2.length()); 44 | return sampleStrings; 45 | } 46 | 47 | // Sort by length with sorted 48 | @SuppressWarnings("ComparatorCombinators") 49 | public List lengthSortUsingSorted() { 50 | return sampleStrings.stream() 51 | .sorted((s1, s2) -> s1.length() - s2.length()) 52 | .collect(toList()); 53 | } 54 | 55 | // Length sort with comparingInt 56 | public List lengthSortUsingComparator() { 57 | return sampleStrings.stream() 58 | .sorted(Comparator.comparingInt(String::length)) 59 | .collect(toList()); 60 | } 61 | 62 | // Sort by length then alpha using sorted 63 | public List lengthSortThenAlphaSort() { 64 | return sampleStrings.stream() 65 | .sorted(comparing(String::length) 66 | .thenComparing(naturalOrder())) 67 | .collect(toList()); 68 | } 69 | 70 | // Sort by length then reverse alpha using sorted 71 | public List lengthSortThenReverseAlphaSort() { 72 | return sampleStrings.stream() 73 | .sorted(comparing(String::length) 74 | .thenComparing(reverseOrder())) 75 | .collect(toList()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/streams/LazyStreams.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import java.util.stream.IntStream; 4 | 5 | public class LazyStreams { 6 | 7 | private int multByTwo(int n) { 8 | System.out.printf("Inside multByTwo with arg %d%n", n); 9 | return n * 2; 10 | } 11 | 12 | private boolean divByThree(int n) { 13 | System.out.printf("Inside divByThree with arg %d%n", n); 14 | return n % 3 == 0; 15 | } 16 | 17 | 18 | public int firstEvenDivBy3() { 19 | return IntStream.range(100, 200) 20 | .filter(x -> x % 3 == 0) 21 | .map(x -> x * 2) 22 | .findFirst().orElse(0); 23 | } 24 | 25 | public int firstEvenDivBy3Verbose() { 26 | return IntStream.range(100, 200) 27 | .filter(this::divByThree) 28 | .map(this::multByTwo) 29 | .findFirst().orElse(0); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/streams/MapFilterReduce.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.function.IntPredicate; 6 | 7 | public class MapFilterReduce { 8 | public static final IntPredicate EVENS = n -> n % 2 == 0; 9 | public static final IntPredicate ODDS = n -> n % 2 != 0; 10 | 11 | private final List strings = Arrays.asList("this", "is", "a", 12 | "list", "of", "strings"); 13 | 14 | public int sumAllLengths() { 15 | return strings.stream() 16 | .mapToInt(String::length) 17 | .sum(); 18 | } 19 | 20 | public int sumEvenLengthStrings() { 21 | return strings.stream() 22 | .mapToInt(String::length) 23 | .filter(n -> n % 2 == 0) 24 | .sum(); 25 | } 26 | 27 | public int sumOddLengthStrings() { 28 | return strings.stream() 29 | .mapToInt(String::length) 30 | .filter(n -> n % 2 != 0) 31 | .sum(); 32 | } 33 | 34 | public int sumStrings(IntPredicate predicate) { 35 | return strings.stream() 36 | .mapToInt(String::length) 37 | .filter(predicate) 38 | .sum(); 39 | } 40 | } -------------------------------------------------------------------------------- /src/main/java/streams/RandomStreams.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | public class RandomStreams { 8 | public static final int LIMIT = 10; 9 | 10 | public static void main(String[] args) { 11 | Random r = new Random(); 12 | r.ints() 13 | .limit(LIMIT) 14 | .sorted() 15 | .forEach(System.out::println); 16 | 17 | r.doubles() 18 | .limit(LIMIT) 19 | .filter(x -> x < 0.5) 20 | .sorted() 21 | .forEach(System.out::println); 22 | 23 | List longs = r.longs() 24 | .limit(LIMIT) 25 | .mapToObj(Long::toString) 26 | .toList(); 27 | System.out.println(longs); 28 | 29 | List listOfInts = r.ints() 30 | .limit(LIMIT) 31 | .collect(ArrayList::new, ArrayList::add, ArrayList::addAll); 32 | System.out.println(listOfInts); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/streams/SumNumbers.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import java.util.List; 4 | 5 | public class SumNumbers { 6 | public static int getTotal(List numbers) { 7 | return numbers.stream() 8 | .filter(n -> n % 3 == 0) 9 | .map(n -> n * 2) 10 | // .reduce(0, (acc, val) -> acc + val); 11 | .reduce(0, Integer::sum); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/main/kotlin/astro/AstroRequest.kt: -------------------------------------------------------------------------------- 1 | package astro 2 | 3 | import com.google.gson.Gson 4 | import java.net.URL 5 | 6 | class AstroRequest { 7 | companion object { 8 | private const val ASTRO_URL = "http://api.open-notify.org/astros.json" 9 | } 10 | 11 | fun execute() : AstroResult { 12 | val responseString = URL(ASTRO_URL).readText() 13 | return Gson().fromJson(responseString, AstroResult::class.java) 14 | } 15 | } -------------------------------------------------------------------------------- /src/main/kotlin/astro/AstroResult.kt: -------------------------------------------------------------------------------- 1 | package astro 2 | 3 | data class AstroResult(val message: String, 4 | val number: Number, 5 | val people: List) 6 | 7 | data class Assignment(val craft: String, 8 | val name: String) 9 | -------------------------------------------------------------------------------- /src/main/kotlin/coroutines/downloadImages.kt: -------------------------------------------------------------------------------- 1 | package coroutines 2 | 3 | import kotlinx.coroutines.* 4 | import java.net.URL 5 | import kotlin.system.measureTimeMillis 6 | 7 | fun downloadImage(url: String) = URL(url).readBytes() 8 | 9 | fun downloadText(url: String) = URL(url).readText() 10 | 11 | suspend fun downloadAll(urls: List) = coroutineScope { 12 | urls.map { 13 | withContext(Dispatchers.IO) { 14 | async { 15 | // downloadImage(it) 16 | downloadText(it) 17 | } 18 | } 19 | }.awaitAll() 20 | } 21 | 22 | fun main() { 23 | runBlocking { 24 | measureTimeMillis { 25 | downloadAll(listOf("http://api.open-notify.org/astros.json", 26 | "http://api.open-notify.org/astros.json", 27 | "http://api.open-notify.org/astros.json", 28 | "http://api.open-notify.org/astros.json", 29 | "http://api.open-notify.org/astros.json")) 30 | }.also(::println) 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/extension/Yoda.kt: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import com.google.gson.Gson 4 | import java.io.File 5 | import java.net.URI 6 | import java.net.URLEncoder 7 | import java.net.http.HttpClient 8 | import java.net.http.HttpRequest 9 | import java.net.http.HttpResponse 10 | 11 | // JSON response to extension.yoda translator 12 | // https://funtranslations.com/api/yoda 13 | // 14 | // { 15 | // "success": { 16 | // "total": 1 17 | // }, 18 | // "contents": { 19 | // "translation": "extension.yoda", 20 | // "text": "Master Obiwan has lost a planet.", 21 | // "translated": "" 22 | // } 23 | // } 24 | 25 | data class YodaResponse(val success: YodaSuccess, 26 | val contents: YodaContents) 27 | 28 | data class YodaSuccess(val total: Int) 29 | 30 | data class YodaContents(val translation: String, 31 | val text: String, 32 | val translated: String) 33 | 34 | const val base = "https://api.funtranslations.com/translate/yoda.json?" 35 | 36 | fun String.yoda(): String { 37 | val key = File("src/main/resources/yoda_key.txt").readText() 38 | val qs = "text=${URLEncoder.encode(this, "UTF-8")}" 39 | 40 | val client: HttpClient = HttpClient.newBuilder().build() 41 | 42 | val request: HttpRequest = HttpRequest.newBuilder() 43 | .uri(URI.create("$base$qs")) 44 | .header("X-FunTranslations-Api-Secret", key) 45 | .GET() 46 | .build() 47 | 48 | val response = client.send(request, HttpResponse.BodyHandlers.ofString()) 49 | 50 | return Gson().fromJson(response.body(), YodaResponse::class.java) 51 | .contents.translated 52 | } 53 | 54 | fun main() { 55 | File("src/main/resources/strings.txt").useLines { sequence -> 56 | sequence.forEach { println(it.yoda()) } 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/extension/palindrome.kt: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import java.util.* 4 | 5 | fun String.isPalindrome() = 6 | this.lowercase(Locale.getDefault()) 7 | .replace("""[\W+]""".toRegex(), "") 8 | .let { it == it.reversed() } 9 | 10 | fun isPal(string: String): Boolean { 11 | val testString = string.lowercase(Locale.getDefault()) 12 | .replace("""[\W+]""".toRegex(), "") 13 | return testString == testString.reversed() 14 | } 15 | -------------------------------------------------------------------------------- /src/main/kotlin/flickr/FlickrGateway.kt: -------------------------------------------------------------------------------- 1 | package flickr 2 | 3 | import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory 4 | import kotlinx.coroutines.* 5 | import kotlinx.serialization.ExperimentalSerializationApi 6 | import kotlinx.serialization.Serializable 7 | import kotlinx.serialization.json.Json 8 | import okhttp3.MediaType 9 | import retrofit2.Retrofit 10 | import retrofit2.http.GET 11 | import retrofit2.http.Query 12 | import java.io.File 13 | import java.net.URL 14 | import javax.imageio.ImageIO 15 | 16 | class FlickrGateway { 17 | 18 | companion object { 19 | val key = File("flickr_key.txt").readText() 20 | } 21 | 22 | @OptIn(ExperimentalSerializationApi::class) 23 | val retrofit: Retrofit = Retrofit.Builder() 24 | .baseUrl("https://api.flickr.com/") 25 | .addConverterFactory( 26 | Json.asConverterFactory(MediaType.get("application/json")) 27 | ) 28 | .build() 29 | 30 | val retrofitService: FlickrService by lazy { 31 | retrofit.create(FlickrService::class.java) 32 | } 33 | 34 | // Problem: Retrofit needs the baseurl argument to @GET to be a compile-time constant 35 | // but Flickr generates the photo urls from the individual photo objects 36 | // So have to do everything manually instead 37 | suspend fun flickrResult2Image() = coroutineScope { 38 | val photoList = retrofitService.getFlickrResult("kitties") 39 | .photos.photo 40 | photoList.map { p -> 41 | val url = "https://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg" 42 | async { 43 | withContext(Dispatchers.IO) { 44 | println("${Thread.currentThread()} ${p.title}") 45 | ImageIO.read(URL(url)) 46 | } 47 | } 48 | }.awaitAll() 49 | } 50 | } 51 | 52 | interface FlickrService { 53 | @GET("services/rest") 54 | suspend fun getFlickrResult( 55 | @Query("tags") tags: String, 56 | @Query("method") method: String = "flickr.photos.search", 57 | @Query("api_key") apiKey: String = FlickrGateway.key, 58 | @Query("format") format: String = "json", 59 | @Query("nojsoncallback") nojsoncallback: Int = 1, 60 | @Query("media") media: String = "photos", 61 | @Query("per_page") perPage: Int = 6 62 | ): FlickrResult 63 | } 64 | 65 | @Serializable 66 | data class FlickrResult( 67 | val photos: PhotoComposite, 68 | val stat: String, 69 | ) 70 | 71 | @Serializable 72 | data class PhotoComposite( 73 | val page: Int, 74 | val pages: Int, 75 | val perpage: Int, 76 | val total: Int, 77 | val photo: List, 78 | ) 79 | 80 | @Serializable 81 | data class Photo( 82 | val id: Long, 83 | val owner: String, 84 | val secret: String, 85 | val server: Int, 86 | val farm: Int, 87 | val title: String, 88 | val ispublic: Int, 89 | val isfriend: Int, 90 | val isfamily: Int, 91 | ) 92 | -------------------------------------------------------------------------------- /src/main/kotlin/functional/algorithms.kt: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import java.math.BigInteger 4 | 5 | fun sum(vararg nums: Int) = 6 | nums.fold(0) { acc, n -> acc + n } 7 | 8 | fun sumWithTrace(vararg nums: Int) = 9 | nums.fold(0) { acc, n -> 10 | println("acc = $acc, n = $n") 11 | acc + n 12 | } 13 | 14 | fun sumReduce(vararg nums: Int) = 15 | nums.reduce { acc, i -> acc + i } 16 | 17 | fun sumReduceDoubles(vararg nums: Int) = 18 | nums.reduce { acc, i -> 19 | println("acc=$acc, i=$i") 20 | acc + 2 * i 21 | } 22 | 23 | @JvmOverloads 24 | tailrec fun fibonacci(n: Int, a: Int = 0, b: Int = 1): Int = 25 | when (n) { 26 | 0 -> a 27 | 1 -> b 28 | else -> fibonacci(n - 1, b, a + b) 29 | } 30 | 31 | fun fibonacciFold(n: Int) = 32 | (2 until n).fold(1 to 1) { 33 | (prev, curr), _ -> curr to (prev + curr) }.second 34 | 35 | fun fibonacciFoldDebug(n: Int) = 36 | (2 until n).fold(1 to 1) { (prev, curr), _ -> 37 | println("prev=$prev, curr=$curr") 38 | curr to (prev + curr) 39 | }.second 40 | 41 | 42 | fun recursiveFactorial(n: Long): BigInteger = 43 | when (n) { 44 | 0L, 1L -> BigInteger.ONE 45 | else -> BigInteger.valueOf(n) * recursiveFactorial(n - 1) 46 | } 47 | 48 | fun factorialFold(n: Long): BigInteger = 49 | when (n) { 50 | 0L, 1L -> BigInteger.ONE 51 | else -> (2..n).fold(BigInteger.ONE) { acc, i -> 52 | acc * BigInteger.valueOf(i) 53 | } 54 | } 55 | 56 | @JvmOverloads 57 | tailrec fun factorial(n: Long, acc: BigInteger = BigInteger.ONE): BigInteger = 58 | when (n) { 59 | 0L -> BigInteger.ONE 60 | 1L -> acc 61 | else -> factorial(n - 1, acc * BigInteger.valueOf(n)) 62 | } 63 | 64 | // fun BigInteger.length() = Math.log10(this.toDouble()).toLong() + 1 -------------------------------------------------------------------------------- /src/main/kotlin/functional/composition.kt: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | // from reference docs: 4 | // https://kotlinlang.org/docs/reference/reflection.html#example-function-composition 5 | 6 | fun compose(f: (B) -> C, g: (A) -> B): (A) -> C = 7 | { x -> f(g(x)) } 8 | 9 | fun length(s: String) = s.length 10 | 11 | fun isOdd(x: Int) = x % 2 == 1 12 | 13 | fun main() { 14 | val oddLength = compose(::isOdd, ::length) 15 | val strings = listOf("a", "ab", "abc") 16 | 17 | strings.filter(oddLength) 18 | .also(::println) 19 | } -------------------------------------------------------------------------------- /src/main/kotlin/functional/primes.kt: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import kotlin.math.ceil 4 | import kotlin.math.sqrt 5 | 6 | fun Int.isPrime() = 7 | this == 2 || (2..ceil(sqrt(this.toDouble())).toInt()) 8 | .none { divisor -> this % divisor == 0 } 9 | 10 | fun nextPrime(num: Int) = 11 | generateSequence(num + 1) { it + 1 } 12 | .first(Int::isPrime) 13 | 14 | fun firstNPrimes(count: Int) = 15 | generateSequence(2, ::nextPrime) 16 | .take(count) 17 | .toList() 18 | 19 | fun primesLessThan(max: Int): List = 20 | // generateSequence(2) { n -> if (n < max) nextPrime(n) else null } 21 | // .toList().dropLast(1) 22 | generateSequence(2, ::nextPrime) 23 | .takeWhile { it < max } 24 | .toList() 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/kotlin/io/jumble.kt: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | import java.io.File 4 | 5 | class JumbleKotlin { 6 | private val wordMap = 7 | File("src/main/resources/dict/words").useLines { lineSeq -> 8 | lineSeq.filter { it.length == 5 || it.length == 6 } 9 | .groupBy(this::word2key) 10 | } 11 | 12 | private fun word2key(word: String) = 13 | word.toList().sorted().joinToString("") 14 | 15 | fun solve(clue: String) = 16 | wordMap[word2key(clue)] ?: listOf() 17 | 18 | fun solveAll(vararg clues: String) = 19 | clues.map(this::solve) 20 | } 21 | 22 | fun main(args: Array) { 23 | println(JumbleKotlin().solveAll(*args)) 24 | } -------------------------------------------------------------------------------- /src/main/kotlin/lambdas/map_filter_reduce.kt: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | import java.time.LocalDate 4 | import java.time.Month 5 | import java.time.Period 6 | 7 | data class Person(val first: String, 8 | val last: String, 9 | val dob: LocalDate) 10 | 11 | fun calculateAge(person: Person) = 12 | Period.between(person.dob, LocalDate.now()).years 13 | 14 | fun mapFilterReduce() { 15 | val data = listOf(3, 1, 4, 1, 5, 9, 2, 6, 5) 16 | println(data) 17 | val result = data.map { it * 2 } // [6, 2, 8, 2, 10, 18, 4, 12, 10] 18 | .filter { it % 3 == 0 } // [6, 18, 12] 19 | .sum() // 36 20 | println("The sum of the doubles divisible by 3 is $result\n") 21 | } 22 | 23 | val doubler = { x: Int -> x * 2 } 24 | 25 | val multiplier: (Int, Int) -> Int = { x, y -> x * y } 26 | 27 | val isEven: (Int) -> Boolean = { it % 2 == 0 } 28 | 29 | fun isOdd(i: Int) = i % 2 != 0 30 | 31 | fun main() { 32 | mapFilterReduce() 33 | 34 | println(doubler(21)) 35 | println(multiplier(21, 2)) 36 | 37 | val list = listOf(3, 1, 4, 1, 5, 9) 38 | println(list.any(isEven)) 39 | println(list.filter(isEven)) 40 | println(list.filter(::isOdd)) 41 | 42 | println((-3..3).filter { it > 0 }) 43 | println((-3..3).any { it > 0 }) 44 | println((-3..3).all { it > 0 }) 45 | 46 | val avengers = listOf( 47 | Person("Robert", "Downey, Jr.", LocalDate.of(1965, Month.APRIL, 4)), 48 | Person("Chris", "Hemsworth", LocalDate.of(1983, Month.AUGUST, 11)), 49 | Person("Mark", "Ruffalo", LocalDate.of(1967, Month.NOVEMBER, 22)), 50 | Person("Chris", "Evans", LocalDate.of(1981, Month.JUNE, 13)), 51 | Person("Scarlett", "Johansson", LocalDate.of(1984, Month.NOVEMBER, 22)), 52 | Person("Jeremy", "Renner", LocalDate.of(1971, Month.JANUARY, 7)), 53 | Person("Chadwick", "Boseman", LocalDate.of(1977, Month.NOVEMBER, 29)), 54 | Person("Diana", "Rigg", LocalDate.of(1938, Month.JULY, 20))) 55 | 56 | avengers.map { person -> "${person.first} ${person.last} is ${calculateAge(person)} years old" } 57 | .forEach { println(it) } 58 | 59 | val averageAge = avengers.map { calculateAge(it) } 60 | .average() 61 | println("Average age: $averageAge") 62 | 63 | println(avengers.maxByOrNull { it.last }) 64 | println(avengers.maxByOrNull(Person::last)) 65 | 66 | println() 67 | avengers.groupBy { it.dob.month }.forEach { println(it) } 68 | } -------------------------------------------------------------------------------- /src/main/kotlin/scripts/antarctica.kt: -------------------------------------------------------------------------------- 1 | package scripts 2 | 3 | import java.time.Instant 4 | import java.time.ZoneId 5 | 6 | fun main() { 7 | 8 | val regex = """.*Antarctica.*""".toRegex() 9 | val instant = Instant.now() 10 | 11 | val zones = ZoneId.getAvailableZoneIds() 12 | .filter { regex.matches(it) } 13 | .map { instant.atZone(ZoneId.of(it)) } 14 | .sortedBy { it.offset.totalSeconds } 15 | .toList() 16 | 17 | zones.forEach { zdt -> 18 | println(String.format("%7s: %25s %7s", zdt.offset, zdt.zone, 19 | zdt.zone.rules.isDaylightSavings(instant))) 20 | } 21 | 22 | println() 23 | val southPole = instant.atZone(ZoneId.of("Antarctica/South_Pole")) 24 | val dst = southPole.zone.rules.isDaylightSavings(Instant.now()) 25 | println("It is ${southPole.toLocalTime()} (UTC${southPole.offset}) at the South Pole") 26 | println("The South Pole ${if (dst) "is" else "is not"} currently on Daylight Savings Time") 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/kotlin/sequences/lazysequences.kt: -------------------------------------------------------------------------------- 1 | package sequences 2 | 3 | fun firstDoubleUsingCollectionsV1() = 4 | (100 until 200).map { println("doubling $it"); it * 2 } 5 | .filter { println("filtering $it"); it % 3 == 0 } 6 | .first() 7 | 8 | fun firstDoubleUsingCollectionsV2() = 9 | (100 until 200).map { println("doubling $it"); it * 2 } 10 | .first { println("filtering $it"); it % 3 == 0 } 11 | 12 | fun firstDoubleUsingSequences() = 13 | (100 until 2_000_000).asSequence() 14 | .map { println("doubling $it"); it * 2 } 15 | .filter { println("filtering $it"); it % 3 == 0 } 16 | .first() 17 | 18 | 19 | fun main() { 20 | // println(firstDoubleUsingCollectionsV1()) 21 | // println(firstDoubleUsingCollectionsV2()) 22 | println(firstDoubleUsingSequences()) 23 | } -------------------------------------------------------------------------------- /src/main/kotlin/sequences/sequenceFunction.kt: -------------------------------------------------------------------------------- 1 | package sequences 2 | 3 | fun fibonacciSequence() = sequence { 4 | var terms = Pair(0, 1) 5 | 6 | while (true) { 7 | yield(terms.first) 8 | terms = terms.second to terms.first + terms.second 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/kotlin/sequences/sum_numbers.kt: -------------------------------------------------------------------------------- 1 | package sequences 2 | 3 | fun getTotal(nums: List) = 4 | nums.filter { it % 3 == 0 } 5 | .map { it * 2 } 6 | // .sum() 7 | .fold(0) { acc, i -> acc + i } 8 | 9 | fun getTotalUsingSequences(nums: List) = 10 | nums.asSequence() 11 | .filter { it % 3 == 0 } 12 | .map { it * 2 } 13 | .sum() -------------------------------------------------------------------------------- /src/main/resources/dict/README: -------------------------------------------------------------------------------- 1 | Added to this project from my local macOS machine, 21 Jan 2020 2 | -- Ken Kousen 3 | 4 | # @(#)README 8.1 (Berkeley) 6/5/93 5 | # $FreeBSD$ 6 | 7 | WEB ---- (introduction provided by jaw@riacs) ------------------------- 8 | 9 | Welcome to web2 (Webster's Second International) all 234,936 words worth. 10 | The 1934 copyright has lapsed, according to the supplier. The 11 | supplemental 'web2a' list contains hyphenated terms as well as assorted 12 | noun and adverbial phrases. The wordlist makes a dandy 'grep' victim. 13 | 14 | -- James A. Woods {ihnp4,hplabs}!ames!jaw (or jaw@riacs) 15 | 16 | Country names are stored in the file /usr/share/misc/iso3166. 17 | 18 | 19 | FreeBSD Maintenance Notes --------------------------------------------- 20 | 21 | Note that FreeBSD is not maintaining a historical document, we're 22 | maintaining a list of current [American] English spellings. 23 | 24 | A few words have been removed because their spellings have depreciated. 25 | This list of words includes: 26 | corelation (and its derivatives) "correlation" is the preferred spelling 27 | freen typographical error in original file 28 | freend archaic spelling no longer in use; 29 | masks common typo in modern text 30 | 31 | -- 32 | 33 | A list of technical terms has been added in the file 'freebsd'. This 34 | word list contains FreeBSD/Unix lexicon that is used by the system 35 | documentation. It makes a great ispell(1) personal dictionary to 36 | supplement the standard English language dictionary. 37 | -------------------------------------------------------------------------------- /src/main/resources/dict/connectives: -------------------------------------------------------------------------------- 1 | the 2 | of 3 | and 4 | to 5 | a 6 | in 7 | that 8 | is 9 | was 10 | he 11 | for 12 | it 13 | with 14 | as 15 | his 16 | on 17 | be 18 | at 19 | by 20 | i 21 | this 22 | had 23 | not 24 | are 25 | but 26 | from 27 | or 28 | have 29 | an 30 | they 31 | which 32 | one 33 | you 34 | were 35 | her 36 | all 37 | she 38 | there 39 | would 40 | their 41 | we 42 | him 43 | been 44 | has 45 | when 46 | who 47 | will 48 | more 49 | no 50 | if 51 | out 52 | so 53 | said 54 | what 55 | up 56 | its 57 | about 58 | into 59 | than 60 | them 61 | can 62 | only 63 | other 64 | new 65 | some 66 | could 67 | time 68 | these 69 | two 70 | may 71 | then 72 | do 73 | first 74 | any 75 | my 76 | now 77 | such 78 | like 79 | our 80 | over 81 | man 82 | me 83 | even 84 | most 85 | made 86 | after 87 | also 88 | did 89 | many 90 | before 91 | must 92 | through 93 | back 94 | years 95 | where 96 | much 97 | your 98 | way 99 | well 100 | down 101 | should 102 | because 103 | each 104 | just 105 | those 106 | people 107 | mr 108 | how 109 | too 110 | little 111 | state 112 | good 113 | very 114 | make 115 | world 116 | still 117 | own 118 | see 119 | men 120 | work 121 | long 122 | get 123 | here 124 | between 125 | both 126 | life 127 | being 128 | under 129 | never 130 | day 131 | same 132 | another 133 | know 134 | while 135 | last 136 | might 137 | us 138 | great 139 | old 140 | year 141 | off 142 | come 143 | since 144 | against 145 | go 146 | came 147 | right 148 | used 149 | take 150 | three 151 | -------------------------------------------------------------------------------- /src/main/resources/dict/propernames: -------------------------------------------------------------------------------- 1 | Aaron 2 | Adam 3 | Adlai 4 | Adrian 5 | Agatha 6 | Ahmed 7 | Ahmet 8 | Aimee 9 | Al 10 | Alain 11 | Alan 12 | Alastair 13 | Albert 14 | Alberto 15 | Alejandro 16 | Alex 17 | Alexander 18 | Alexis 19 | Alf 20 | Alfred 21 | Alison 22 | Allan 23 | Allen 24 | Alvin 25 | Amanda 26 | Amarth 27 | Amedeo 28 | Ami 29 | Amigo 30 | Amir 31 | Amos 32 | Amy 33 | Anatole 34 | Anatoly 35 | Anderson 36 | Andre 37 | Andrea 38 | Andreas 39 | Andrew 40 | Andries 41 | Andy 42 | Angela 43 | Angus 44 | Anita 45 | Ann 46 | Anna 47 | Annard 48 | Anne 49 | Annie 50 | Anthony 51 | Anton 52 | Antonella 53 | Antonio 54 | Antony 55 | Archie 56 | Ariel 57 | Arlene 58 | Arne 59 | Arnold 60 | Art 61 | Arthur 62 | Audrey 63 | Avery 64 | Axel 65 | Barbara 66 | Barbra 67 | Barney 68 | Barrett 69 | Barrio 70 | Barry 71 | Bart 72 | Barton 73 | Bea 74 | Beckie 75 | Becky 76 | Belinda 77 | Ben 78 | Benjamin 79 | Benson 80 | Bernard 81 | Bernie 82 | Bert 83 | Bertrand 84 | Beth 85 | Betsy 86 | Betty 87 | Beverly 88 | Bill 89 | Billie 90 | Billy 91 | Bjorne 92 | Blaine 93 | Blair 94 | Blake 95 | Blayne 96 | Bob 97 | Bobbie 98 | Bobby 99 | Bonnie 100 | Boyce 101 | Boyd 102 | Brad 103 | Bradford 104 | Bradley 105 | Brandi 106 | Brandon 107 | Brandy 108 | Brenda 109 | Brendan 110 | Brender 111 | Brent 112 | Bret 113 | Brett 114 | Brian 115 | Briggs 116 | Brodie 117 | Brooke 118 | Bruce 119 | Bruno 120 | Bryan 121 | Bryce 122 | Bucky 123 | Bud 124 | Butler 125 | Byron 126 | Caleb 127 | Calvin 128 | Carisa 129 | Carl 130 | Carlo 131 | Carlos 132 | Carol 133 | Carole 134 | Caroline 135 | Carolyn 136 | Carsten 137 | Carter 138 | Cary 139 | Case 140 | Casey 141 | Casper 142 | Catherine 143 | Cathrin 144 | Cathryn 145 | Cathy 146 | Cecilia 147 | Celeste 148 | Celia 149 | Charleen 150 | Charlene 151 | Charles 152 | Charley 153 | Charlie 154 | Chet 155 | Chip 156 | Chris 157 | Christian 158 | Christie 159 | Christina 160 | Christofer 161 | Christophe 162 | Christopher 163 | Chuck 164 | Cindie 165 | Cindy 166 | Claire 167 | Clara 168 | Clare 169 | Clarence 170 | Clarissa 171 | Clark 172 | Claude 173 | Claudia 174 | Claudio 175 | Clay 176 | Clayton 177 | Clem 178 | Cliff 179 | Clifford 180 | Clyde 181 | Cole 182 | Coleen 183 | Colin 184 | Collin 185 | Connie 186 | Conrad 187 | Corey 188 | Cory 189 | Courtney 190 | Craig 191 | Cris 192 | Cristi 193 | Cristina 194 | Cristopher 195 | Curt 196 | Curtis 197 | Cynthia 198 | Cyrus 199 | Dale 200 | Dalton 201 | Damon 202 | Damone 203 | Dan 204 | Dana 205 | Dani 206 | Daniel 207 | Daniele 208 | Danielle 209 | Dannie 210 | Danny 211 | Darci 212 | Daren 213 | Darin 214 | Darrell 215 | Darren 216 | Darryl 217 | Daryl 218 | Dave 219 | David 220 | Dawn 221 | Dawson 222 | Dean 223 | Deb 224 | Debbie 225 | Debi 226 | Deborah 227 | Deirdre 228 | Del 229 | Delbert 230 | Denis 231 | Dennis 232 | Derek 233 | Devon 234 | Dewey 235 | Diana 236 | Diane 237 | Dick 238 | Dieter 239 | Dimetry 240 | Dimitry 241 | Dion 242 | Dirk 243 | Dominic 244 | Dominick 245 | Don 246 | Donal 247 | Donald 248 | Donn 249 | Donna 250 | Donne 251 | Donnie 252 | Donovan 253 | Dori 254 | Dorian 255 | Dorothy 256 | Dory 257 | Doug 258 | Douglas 259 | Doyle 260 | Drew 261 | Duane 262 | Duke 263 | Duncan 264 | Dustin 265 | Dwayne 266 | Dwight 267 | Dylan 268 | Earl 269 | Earle 270 | Earnie 271 | Ed 272 | Eddie 273 | Eddy 274 | Edgar 275 | Edith 276 | Edmond 277 | Edmund 278 | Eduardo 279 | Edward 280 | Edwin 281 | Eileen 282 | Elaine 283 | Eli 284 | Elias 285 | Elijah 286 | Eliot 287 | Elisabeth 288 | Elizabeth 289 | Ellen 290 | Elliot 291 | Elliott 292 | Elric 293 | Elsa 294 | Elvis 295 | Elwood 296 | Emil 297 | Emily 298 | Emma 299 | Emmett 300 | Eric 301 | Erick 302 | Erik 303 | Ernest 304 | Ernie 305 | Ernst 306 | Erwin 307 | Ethan 308 | Eugene 309 | Eva 310 | Evan 311 | Evelyn 312 | Everett 313 | Farouk 314 | Fay 315 | Felix 316 | Fletcher 317 | Floria 318 | Florian 319 | Floyd 320 | Frances 321 | Francis 322 | Francisco 323 | Francois 324 | Frank 325 | Franklin 326 | Fred 327 | Frederic 328 | Frederick 329 | Fritz 330 | Gabriel 331 | Gail 332 | Gale 333 | Galen 334 | Gary 335 | Gene 336 | Geoff 337 | Geoffrey 338 | George 339 | Gerald 340 | Gerard 341 | Gideon 342 | Gigi 343 | Gil 344 | Giles 345 | Gill 346 | Gilles 347 | Ginny 348 | Giovanni 349 | Glen 350 | Glenn 351 | Glynn 352 | Gordon 353 | Grace 354 | Graeme 355 | Graham 356 | Grant 357 | Granville 358 | Greg 359 | Gregg 360 | Gregge 361 | Gregor 362 | Gregory 363 | Gretchen 364 | Griff 365 | Guido 366 | Guillermo 367 | Gunnar 368 | Gunter 369 | Guy 370 | Gypsy 371 | Hal 372 | Hamilton 373 | Hank 374 | Hans 375 | Harmon 376 | Harold 377 | Harris 378 | Harry 379 | Hartmann 380 | Harv 381 | Harvey 382 | Hazel 383 | Heather 384 | Hector 385 | Heidi 386 | Hein 387 | Heinrich 388 | Heinz 389 | Helen 390 | Helge 391 | Henry 392 | Herb 393 | Herbert 394 | Herman 395 | Herve 396 | Hienz 397 | Hilda 398 | Hillary 399 | Hillel 400 | Himawan 401 | Hirofumi 402 | Hirotoshi 403 | Hiroyuki 404 | Hitoshi 405 | Hohn 406 | Holly 407 | Hon 408 | Honzo 409 | Horst 410 | Hotta 411 | Howard 412 | Hsi 413 | Hsuan 414 | Huashi 415 | Hubert 416 | Huey 417 | Hugh 418 | Hughes 419 | Hui 420 | Hume 421 | Hunter 422 | Hurf 423 | Hwa 424 | Hy 425 | Ian 426 | Ilya 427 | Ima 428 | Indra 429 | Ira 430 | Irfan 431 | Irvin 432 | Irving 433 | Irwin 434 | Isaac 435 | Isabelle 436 | Isidore 437 | Israel 438 | Izchak 439 | Izumi 440 | Izzy 441 | Jack 442 | Jackye 443 | Jacob 444 | Jacobson 445 | Jacques 446 | Jagath 447 | Jaime 448 | Jakob 449 | James 450 | Jamie 451 | Jan 452 | Jane 453 | Janet 454 | Janice 455 | Janos 456 | Jared 457 | Jarl 458 | Jarmo 459 | Jarvis 460 | Jason 461 | Jay 462 | Jayant 463 | Jayesh 464 | Jean 465 | Jean-Christophe 466 | Jean-Pierre 467 | Jeanette 468 | Jeanne 469 | Jeannette 470 | Jeannie 471 | Jeany 472 | Jef 473 | Jeff 474 | Jeffery 475 | Jeffie 476 | Jeffrey 477 | Jelske 478 | Jem 479 | Jenine 480 | Jennie 481 | Jennifer 482 | Jerald 483 | Jeremy 484 | Jerome 485 | Jerrie 486 | Jerry 487 | Jesper 488 | Jess 489 | Jesse 490 | Jesus 491 | Ji 492 | Jianyun 493 | Jill 494 | Jim 495 | Jimmy 496 | Jin 497 | Jinchao 498 | Jingbai 499 | Jinny 500 | Jiri 501 | Jisheng 502 | Jitendra 503 | Joachim 504 | Joanne 505 | Jochen 506 | Jock 507 | Joe 508 | Joel 509 | Johan 510 | Johann 511 | John 512 | Johnathan 513 | Johnnie 514 | Johnny 515 | Jon 516 | Jonathan 517 | Jones 518 | Jong 519 | Joni 520 | Joon 521 | Jordan 522 | Jorge 523 | Jos 524 | Jose 525 | Joseph 526 | Josh 527 | Joshua 528 | Josip 529 | Joubert 530 | Joyce 531 | Juan 532 | Judge 533 | Judith 534 | Judy 535 | Juergen 536 | Juha 537 | Julia 538 | Julian 539 | Juliane 540 | Julianto 541 | Julie 542 | Juliet 543 | Julius 544 | Jun 545 | June 546 | Jurevis 547 | Juri 548 | Jussi 549 | Justin 550 | Jwahar 551 | Kaj 552 | Kamel 553 | Kamiya 554 | Kanthan 555 | Karen 556 | Kari 557 | Karl 558 | Kate 559 | Kathleen 560 | Kathryn 561 | Kathy 562 | Kay 563 | Kayvan 564 | Kazuhiro 565 | Kee 566 | Kees 567 | Keith 568 | Kelly 569 | Kelvin 570 | Kemal 571 | Ken 572 | Kenn 573 | Kenneth 574 | Kent 575 | Kenton 576 | Kerri 577 | Kerry 578 | Kevan 579 | Kevin 580 | Kevyn 581 | Kieran 582 | Kiki 583 | Kikki 584 | Kim 585 | Kimberly 586 | Kimmo 587 | Kinch 588 | King 589 | Kirk 590 | Kirsten 591 | Kit 592 | Kitty 593 | Klaudia 594 | Klaus 595 | Knapper 596 | Knudsen 597 | Knut 598 | Knute 599 | Kolkka 600 | Konrad 601 | Konstantinos 602 | Kory 603 | Kris 604 | Kristen 605 | Kristi 606 | Kristian 607 | Kristin 608 | Kriton 609 | Krzysztof 610 | Kuldip 611 | Kurt 612 | Kusum 613 | Kyle 614 | Kylo 615 | Kyu 616 | Kyung 617 | Lana 618 | Lance 619 | Lanny 620 | Lar 621 | Larry 622 | Lars 623 | Laura 624 | Laurel 625 | Laurence 626 | Laurent 627 | Laurianne 628 | Laurie 629 | Lawrence 630 | Lea 631 | Leads 632 | Lee 633 | Leif 634 | Leigh 635 | Leila 636 | Leith 637 | Len 638 | Lenny 639 | Lenora 640 | Leo 641 | Leon 642 | Leonard 643 | Leora 644 | Les 645 | Leslie 646 | Lester 647 | Leung 648 | Lewis 649 | Lex 650 | Liber 651 | Lievaart 652 | Lila 653 | Lin 654 | Linda 655 | Linder 656 | Lindsay 657 | Lindsey 658 | Linley 659 | Lisa 660 | List 661 | Liyuan 662 | Liz 663 | Liza 664 | Lloyd 665 | Lois 666 | Lonhyn 667 | Lord 668 | Loren 669 | Lorenzo 670 | Lori 671 | Lorien 672 | Lorraine 673 | Lou 674 | Louie 675 | Louiqa 676 | Louis 677 | Louise 678 | Loukas 679 | Lowell 680 | Loyd 681 | Luc 682 | Lucifer 683 | Lucius 684 | Lui 685 | Luis 686 | Lukas 687 | Luke 688 | Lum 689 | Lyndon 690 | Lynn 691 | Lynne 692 | Lynnette 693 | Maarten 694 | Mac 695 | Magnus 696 | Mah 697 | Mahesh 698 | Mahmoud 699 | Major 700 | Malaclypse 701 | Malcolm 702 | Malloy 703 | Malus 704 | Manavendra 705 | Manjeri 706 | Mann 707 | Manny 708 | Manolis 709 | Manuel 710 | Mara 711 | Marc 712 | Marcel 713 | Marci 714 | Marcia 715 | Marco 716 | Marcos 717 | Marek 718 | Margaret 719 | Margie 720 | Margot 721 | Marguerite 722 | Maria 723 | Marian 724 | Marie 725 | Marilyn 726 | Mario 727 | Marion 728 | Mariou 729 | Mark 730 | Markus 731 | Marla 732 | Marlena 733 | Marnix 734 | Marsh 735 | Marsha 736 | Marshall 737 | Martha 738 | Martin 739 | Marty 740 | Martyn 741 | Marvin 742 | Mary 743 | Masanao 744 | Masanobu 745 | Mason 746 | Mat 747 | Mats 748 | Matt 749 | Matthew 750 | Matthias 751 | Matthieu 752 | Matti 753 | Maureen 754 | Maurice 755 | Max 756 | Mayo 757 | Mechael 758 | Meehan 759 | Meeks 760 | Mehrdad 761 | Melinda 762 | Merat 763 | Merril 764 | Merton 765 | Metin 766 | Micah 767 | Michael 768 | Micheal 769 | Michel 770 | Michelle 771 | Michiel 772 | Mick 773 | Mickey 774 | Micky 775 | Miek 776 | Mikael 777 | Mike 778 | Mikey 779 | Miki 780 | Miles 781 | Milner 782 | Milo 783 | Miltos 784 | Miriam 785 | Miriamne 786 | Mitch 787 | Mitchell 788 | Moe 789 | Mohammad 790 | Molly 791 | Mongo 792 | Monica 793 | Monty 794 | Moore 795 | Moran 796 | Morgan 797 | Morris 798 | Morton 799 | Moses 800 | Mosur 801 | Mott 802 | Murat 803 | Murph 804 | Murray 805 | Murthy 806 | Mwa 807 | Myrick 808 | Myron 809 | Mysore 810 | Nadeem 811 | Naim 812 | Nancy 813 | Nanda 814 | Naomi 815 | Naoto 816 | Naren 817 | Narendra 818 | Naresh 819 | Nate 820 | Nathan 821 | Nathaniel 822 | Natraj 823 | Neal 824 | Ned 825 | Neil 826 | Nelken 827 | Neville 828 | Nguyen 829 | Nhan 830 | Niall 831 | Nichael 832 | Nicholas 833 | Nici 834 | Nick 835 | Nicolas 836 | Nicolette 837 | Nicolo 838 | Niels 839 | Nigel 840 | Nikolai 841 | Nils 842 | Ning 843 | Ninja 844 | No 845 | Noam 846 | Noemi 847 | Nora 848 | Norbert 849 | Norm 850 | Norma 851 | Norman 852 | Nou 853 | Novo 854 | Novorolsky 855 | Ofer 856 | Olaf 857 | Old 858 | Ole 859 | Oleg 860 | Oliver 861 | Olivier 862 | Olof 863 | Olson 864 | Omar 865 | Orville 866 | Oscar 867 | Oskar 868 | Owen 869 | Ozan 870 | Pablo 871 | Page 872 | Pam 873 | Pamela 874 | Panacea 875 | Pandora 876 | Panos 877 | Pantelis 878 | Panzer 879 | Paola 880 | Part 881 | Pascal 882 | Pat 883 | Patrice 884 | Patricia 885 | Patricio 886 | Patrick 887 | Patty 888 | Paul 889 | Paula 890 | Pedro 891 | Peggy 892 | Penny 893 | Per 894 | Perry 895 | Pete 896 | Peter 897 | Petr 898 | Phil 899 | Philip 900 | Philippe 901 | Phill 902 | Phillip 903 | Phiroze 904 | Pia 905 | Piercarlo 906 | Pierce 907 | Pierette 908 | Pierre 909 | Piet 910 | Piete 911 | Pieter 912 | Pilar 913 | Pilot 914 | Pim 915 | Ping 916 | Piotr 917 | Pitawas 918 | Plastic 919 | Po 920 | Polly 921 | Pontus 922 | Pradeep 923 | Prakash 924 | Pratap 925 | Pratapwant 926 | Pratt 927 | Pravin 928 | Presley 929 | Pria 930 | Price 931 | Raanan 932 | Rabin 933 | Radek 934 | Rafael 935 | Rafik 936 | Raghu 937 | Ragnar 938 | Rahul 939 | Raif 940 | Rainer 941 | Raj 942 | Raja 943 | Rajarshi 944 | Rajeev 945 | Rajendra 946 | Rajesh 947 | Rajiv 948 | Rakhal 949 | Ralf 950 | Ralph 951 | Ram 952 | Ramadoss 953 | Raman 954 | Ramanan 955 | Ramesh 956 | Ramiro 957 | Ramneek 958 | Ramon 959 | Ramsey 960 | Rand 961 | Randal 962 | Randall 963 | Randell 964 | Randolph 965 | Randy 966 | Ranjit 967 | Raphael 968 | Rathnakumar 969 | Raul 970 | Ravi 971 | Ravindran 972 | Ravindranath 973 | Ray 974 | Rayan 975 | Raymond 976 | Real 977 | Rebecca 978 | Rees 979 | Reid 980 | Reiner 981 | Reinhard 982 | Renu 983 | Revised 984 | Rex 985 | Rhonda 986 | Ric 987 | Ricardo 988 | Rich 989 | Richard 990 | Rick 991 | Ricky 992 | Rik 993 | Ritalynne 994 | Ritchey 995 | Ro 996 | Rob 997 | Robbin 998 | Robert 999 | Roberta 1000 | Roberto 1001 | Robin 1002 | Rod 1003 | Rodent 1004 | Roderick 1005 | Rodger 1006 | Rodney 1007 | Roger 1008 | Rogue 1009 | Roland 1010 | Rolf 1011 | Rolfe 1012 | Romain 1013 | Roman 1014 | Ron 1015 | Ronald 1016 | Ronni 1017 | Root 1018 | Ross 1019 | Roxana 1020 | Roxane 1021 | Roxanne 1022 | Roxie 1023 | Roy 1024 | Rudolf 1025 | Rudolph 1026 | Rudy 1027 | Rupert 1028 | Russ 1029 | Russell 1030 | Rusty 1031 | Ruth 1032 | Saad 1033 | Sabrina 1034 | Saify 1035 | Saiid 1036 | Sal 1037 | Sally 1038 | Sam 1039 | Samir 1040 | Samuel 1041 | Sanand 1042 | Sanche 1043 | Sandeep 1044 | Sandip 1045 | Sandra 1046 | Sandy 1047 | Sanford 1048 | Sangho 1049 | Sanity 1050 | Sanjay 1051 | Sanjeev 1052 | Sanjib 1053 | Santa 1054 | Saqib 1055 | Sarah 1056 | Sassan 1057 | Saul 1058 | Saumya 1059 | Scot 1060 | Scott 1061 | Sean 1062 | Sedat 1063 | Sedovic 1064 | Seenu 1065 | Sehyo 1066 | Sekar 1067 | Serdar 1068 | Sergeant 1069 | Sergei 1070 | Sergio 1071 | Sergiu 1072 | Seth 1073 | Seymour 1074 | Shadow 1075 | Shahid 1076 | Shai 1077 | Shakil 1078 | Shamim 1079 | Shane 1080 | Shankar 1081 | Shannon 1082 | Sharada 1083 | Sharan 1084 | Shari 1085 | Sharon 1086 | Shatter 1087 | Shaw 1088 | Shawn 1089 | Shean 1090 | Sheila 1091 | Shel 1092 | Sherman 1093 | Sherri 1094 | Shirley 1095 | Sho 1096 | Shutoku 1097 | Shuvra 1098 | Shyam 1099 | Sid 1100 | Sidney 1101 | Siegurd 1102 | Sigurd 1103 | Simon 1104 | Siping 1105 | Sir 1106 | Sjaak 1107 | Sjouke 1108 | Skeeter 1109 | Skef 1110 | Skip 1111 | Slartibartfast 1112 | Socorrito 1113 | Sofia 1114 | Sofoklis 1115 | Son 1116 | Sonja 1117 | Sonny 1118 | Soohong 1119 | Sorrel 1120 | Space 1121 | Spass 1122 | Spencer 1123 | Spike 1124 | Spock 1125 | Spudboy 1126 | Spy 1127 | Spyros 1128 | Sri 1129 | Sridhar 1130 | Sridharan 1131 | Srikanth 1132 | Srinivas 1133 | Srinivasan 1134 | Sriram 1135 | Srivatsan 1136 | Ssi 1137 | Stacey 1138 | Stacy 1139 | Stagger 1140 | Stan 1141 | Stanislaw 1142 | Stanley 1143 | Stanly 1144 | Starbuck 1145 | Steen 1146 | Stefan 1147 | Stephan 1148 | Stephanie 1149 | Stephe 1150 | Stephen 1151 | Stevan 1152 | Steve 1153 | Steven 1154 | Stewart 1155 | Straka 1156 | Stu 1157 | Stuart 1158 | Subra 1159 | Sue 1160 | Sugih 1161 | Sumitro 1162 | Sundar 1163 | Sundaresan 1164 | Sunil 1165 | Suresh 1166 | Surya 1167 | Susan 1168 | Susanne 1169 | Susumu 1170 | Suu 1171 | Suwandi 1172 | Suyog 1173 | Suzan 1174 | Suzanne 1175 | Svante 1176 | Swamy 1177 | Syd 1178 | Syed 1179 | Sylvan 1180 | Syun 1181 | Tad 1182 | Tahsin 1183 | Tai 1184 | Tait 1185 | Takao 1186 | Takayuki 1187 | Takeuchi 1188 | Tal 1189 | Tammy 1190 | Tanaka 1191 | Tandy 1192 | Tanya 1193 | Tao 1194 | Tareq 1195 | Tarmi 1196 | Taurus 1197 | Ted 1198 | Teresa 1199 | Teri 1200 | Teriann 1201 | Terrance 1202 | Terrence 1203 | Terri 1204 | Terry 1205 | Teruyuki 1206 | Thad 1207 | Tharen 1208 | The 1209 | Theo 1210 | Theodore 1211 | Thierry 1212 | Think 1213 | Thomas 1214 | Those 1215 | Thuan 1216 | Ti 1217 | Tiefenthal 1218 | Tigger 1219 | Tim 1220 | Timo 1221 | Timothy 1222 | Tobias 1223 | Toby 1224 | Todd 1225 | Toerless 1226 | Toft 1227 | Tolerant 1228 | Tollefsen 1229 | Tom 1230 | Tomas 1231 | Tommy 1232 | Tony 1233 | Tor 1234 | Torsten 1235 | Toufic 1236 | Tovah 1237 | Tracey 1238 | Tracy 1239 | Tran 1240 | Travis 1241 | Trent 1242 | Trevor 1243 | Trey 1244 | Triantaphyllos 1245 | Tricia 1246 | Troy 1247 | Trying 1248 | Tuan 1249 | Tuna 1250 | Turkeer 1251 | Tyler 1252 | Uri 1253 | Urs 1254 | Vadim 1255 | Val 1256 | Valentin 1257 | Valeria 1258 | Valerie 1259 | Van 1260 | Vance 1261 | Varda 1262 | Vassos 1263 | Vaughn 1264 | Venkata 1265 | Vern 1266 | Vernon 1267 | Vic 1268 | Vice 1269 | Vick 1270 | Vicki 1271 | Vickie 1272 | Vicky 1273 | Victor 1274 | Victoria 1275 | Vidhyanath 1276 | Vijay 1277 | Vilhelm 1278 | Vince 1279 | Vincent 1280 | Vincenzo 1281 | Vinod 1282 | Vishal 1283 | Vistlik 1284 | Vivek 1285 | Vladimir 1286 | Vladislav 1287 | Wade 1288 | Walt 1289 | Walter 1290 | Warren 1291 | Wayne 1292 | Wendell 1293 | Wendi 1294 | Wendy 1295 | Werner 1296 | Wes 1297 | Will 1298 | William 1299 | Willie 1300 | Wilmer 1301 | Wilson 1302 | Win 1303 | Winnie 1304 | Winston 1305 | Wolf 1306 | Wolfgang 1307 | Woody 1308 | Yvonne 1309 | -------------------------------------------------------------------------------- /src/main/resources/strings.txt: -------------------------------------------------------------------------------- 1 | Do, or do not. There is no try. 2 | I'd like to add you to my professional network on LinkedIn 3 | Please complete your session evals -------------------------------------------------------------------------------- /src/main/resources/yoda_key.txt: -------------------------------------------------------------------------------- 1 | ftf27tWvV2EiR90zo_fY1weF -------------------------------------------------------------------------------- /src/test/groovy/functional/annotations/AnnotatedFunctionsTest.groovy: -------------------------------------------------------------------------------- 1 | package functional.annotations 2 | 3 | import spock.lang.Specification 4 | 5 | class AnnotatedFunctionsTest extends Specification { 6 | AnnotatedFunctions af = new AnnotatedFunctions() 7 | 8 | def "fibonacci"() { 9 | expect: 10 | fibn == af.fib(n as BigInteger) 11 | 12 | where: 13 | n || fibn 14 | 1 || 1 15 | 2 || 1 16 | 3 || 2 17 | 4 || 3 18 | 5 || 5 19 | 6 || 8 20 | 7 || 13 21 | 8 || 21 22 | 9 || 34 23 | 10 || 55 24 | } 25 | 26 | def "factorial with memoize"() { 27 | expect: 28 | factn == af.fact(n as BigInteger) 29 | 30 | where: 31 | n || factn 32 | 0 || 1 33 | 1 || 1 34 | 2 || 2 35 | 3 || 3 * 2 36 | 4 || 4 * 3 * 2 37 | 5 || 5 * 4 * 3 * 2 38 | 6 || 6 * 5 * 4 * 3 * 2 39 | 7 || 7 * 6 * 5 * 4 * 3 * 2 40 | 8 || 8 * 7 * 6 * 5 * 4 * 3 * 2 41 | } 42 | 43 | def "factorial with tail recursion"() { 44 | expect: 45 | factn == af.factorial(n as BigInteger) 46 | 47 | where: 48 | n || factn 49 | 0 || 1 50 | 1 || 1 51 | 2 || 2 52 | 3 || 3 * 2 53 | 4 || 4 * 3 * 2 54 | 5 || 5 * 4 * 3 * 2 55 | 6 || 6 * 5 * 4 * 3 * 2 56 | 7 || 7 * 6 * 5 * 4 * 3 * 2 57 | 8 || 8 * 7 * 6 * 5 * 4 * 3 * 2 58 | } 59 | 60 | def "greatest common denominator"() { 61 | expect: 62 | 24 == af.gcd(48, 72) 63 | 14 == af.gcd(182, 154) 64 | } 65 | 66 | // Example from GroovyDocs on @TailRecursive 67 | def "sum up to a given number with tail recursion"() { 68 | expect: 69 | 5050L == af.sumUp(100) 70 | 500_000_500_000 == af.sumUp(1_000_000) 71 | } 72 | 73 | // Example from GroovyDocs on @TailRecursive 74 | def 'sizeOfList'() { 75 | expect: 76 | 10_000L == af.sizeOfList(1..10000) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/test/groovy/functional/immutables/PointSpec.groovy: -------------------------------------------------------------------------------- 1 | package functional.immutables 2 | 3 | import spock.lang.Specification 4 | 5 | class PointSpec extends Specification { 6 | def 'tuple constructor works'() { 7 | expect: new Point(3, 4) 8 | } 9 | 10 | def "can translate"() { 11 | given: 12 | Point start = new Point(1, 0) 13 | Point end = new Point(3, 3) 14 | 15 | when: 16 | Point p = start.translate(2, 3) 17 | 18 | then: 19 | assert (p.x - end.x).abs() < 1e-10 20 | assert (p.y - end.y).abs() < 1e-10 21 | 22 | } 23 | 24 | def "can rotate 90 deg"() { 25 | given: 26 | Point p = new Point(1, 0) 27 | 28 | when: 29 | p = p.rotate(Math.PI / 2) 30 | 31 | then: 32 | p.x.abs() < 1e-10 33 | p.y == 1 34 | } 35 | 36 | def "can rotate 180 deg"() { 37 | given: 38 | Point p = new Point(1, 0) 39 | 40 | when: 41 | p = p.rotate(Math.PI) 42 | 43 | then: 44 | p.x == -1 45 | p.y.abs() < 1e-10 46 | } 47 | 48 | def "overloaded plus"() { 49 | given: 50 | Point p1 = new Point(1, 2) 51 | Point p2 = new Point(3, 4) 52 | 53 | when: 54 | Point p = p1 + p2 55 | 56 | then: 57 | p.x == 4 58 | p.y == 6 59 | } 60 | 61 | def "overloaded minus"() { 62 | given: 63 | Point p1 = new Point(1, 2) 64 | Point p2 = new Point(3, 4) 65 | 66 | when: 67 | Point p = p1 - p2 68 | 69 | then: 70 | p.x == -2 71 | p.y == -2 72 | } 73 | 74 | def "can't change x"() { 75 | given: 76 | Point p = new Point(1, 2) 77 | 78 | when: 79 | p.x = 5 80 | 81 | then: 82 | thrown(ReadOnlyPropertyException) 83 | } 84 | 85 | def "can't change y"() { 86 | given: 87 | Point p = new Point(1, 2) 88 | 89 | when: 90 | p.y = 5 91 | 92 | then: 93 | thrown(ReadOnlyPropertyException) 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/test/groovy/io/JumbleSpec.groovy: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | 4 | import spock.lang.Specification 5 | import spock.lang.Unroll 6 | 7 | class JumbleSpec extends Specification { 8 | 9 | @Unroll 10 | void "unscramble #scrambled to get #word"() { 11 | given: 12 | Jumble1 jumble1 = new Jumble1() 13 | Jumble2 jumble2 = new Jumble2() 14 | 15 | expect: 16 | jumble1.solve(scrambled) == word 17 | jumble2.solve(scrambled) == word 18 | 19 | where: 20 | scrambled || word 21 | 'cautla' || ['actual'] 22 | 'agileo' || ['goalie'] 23 | 'mmlueb' || ['mumble'] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/groovy/lambdas/PrimeCheckerSpec.groovy: -------------------------------------------------------------------------------- 1 | package lambdas 2 | 3 | import spock.lang.Specification 4 | import spock.lang.Unroll 5 | 6 | class PrimeCheckerSpec extends Specification { 7 | PrimeChecker pc = new PrimeChecker() 8 | PrimeCheckerGroovy pcg = new PrimeCheckerGroovy() 9 | 10 | @Unroll 11 | def "#x is prime"() { 12 | expect: 13 | pc.isPrime(x) 14 | pc.isPrimeJava7(x) 15 | pcg.isPrime(x) 16 | 17 | where: 18 | x << [2, 3, 5, 7, 11, 13, 17, 19] 19 | } 20 | 21 | @Unroll 22 | def "#x is not prime"() { 23 | expect: 24 | !pc.isPrime(x) 25 | !pcg.isPrime(x) 26 | 27 | where: 28 | x << [4, 6, 8, 9, 10, 12, 14, 15, 16, 18] 29 | } 30 | 31 | @Unroll 32 | def '#x throws IllegalArgumentException'() { 33 | when: 34 | pc.isPrime(x) 35 | 36 | then: 37 | thrown(IllegalArgumentException) 38 | 39 | where: 40 | x << (-2..1) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/groovy/sorting/SortingDemoGroovySpec.groovy: -------------------------------------------------------------------------------- 1 | package sorting 2 | 3 | import spock.lang.Specification 4 | 5 | class SortingDemoGroovySpec extends Specification { 6 | SortingDemoGroovy demo = new SortingDemoGroovy() 7 | 8 | private boolean checkAlpha(List list) { 9 | list.inject('') { prev, curr -> 10 | assert prev <= curr 11 | curr 12 | } 13 | } 14 | 15 | private boolean checkLength(List list) { 16 | list.inject { String prev, String curr -> 17 | assert prev.size() <= curr.size() 18 | curr 19 | } 20 | } 21 | 22 | def "DefaultSort"() { 23 | expect: 24 | checkAlpha(demo.defaultSort()) 25 | } 26 | 27 | def "LengthSortWithTwoArgClosure"() { 28 | expect: 29 | checkLength(demo.lengthSortWithTwoArgClosure()) 30 | } 31 | 32 | def "LengthSortWithOneArgClosure"() { 33 | expect: 34 | checkLength(demo.lengthSortWithOneArgClosure()) 35 | } 36 | 37 | def "LengthSortThenAlphaSort"() { 38 | when: 39 | List sorted = demo.lengthSortThenAlphaSort() 40 | 41 | then: 42 | sorted.inject { String prev, String curr -> 43 | assert prev.size() <= curr.size() 44 | if (prev.size() == curr.size()) { 45 | assert prev <= curr 46 | } 47 | curr 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/groovy/streams/LazyStreamsSpec.groovy: -------------------------------------------------------------------------------- 1 | package streams 2 | 3 | import spock.lang.Specification 4 | 5 | class LazyStreamsSpec extends Specification { 6 | LazyStreams lz = new LazyStreams() 7 | LazyStreamsGroovy lzg = new LazyStreamsGroovy() 8 | 9 | def "FirstEvenDivBy3"() { 10 | expect: 11 | 204 == lz.firstEvenDivBy3() 12 | 204 == lzg.firstEvenDivBy3() 13 | } 14 | 15 | def "FirstEvenDivBy3Verbose"() { 16 | when: 17 | println 'Java:' 18 | int x = lz.firstEvenDivBy3Verbose() 19 | 20 | then: 21 | x == 204 22 | 23 | when: 24 | println 'Groovy:' 25 | x = lzg.firstEvenDivBy3Verbose() 26 | 27 | then: 28 | x == 204 29 | } 30 | 31 | def 'FirstEvenDivBy3UsingStreams'() { 32 | expect: 33 | 204 == lzg.firstEvenDivBy3UsingStreams() 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/groovy/streams/MapFilterReduceSpec.groovy: -------------------------------------------------------------------------------- 1 | package streams 2 | 3 | import spock.lang.Specification 4 | 5 | class MapFilterReduceSpec extends Specification { 6 | MapFilterReduce demo = new MapFilterReduce() 7 | 8 | def "SumAllLengths"() { 9 | expect: 10 | 20 == demo.sumAllLengths() 11 | } 12 | 13 | def "SumEvenLengthStrings"() { 14 | expect: 15 | 12 == demo.sumEvenLengthStrings() 16 | } 17 | 18 | def "SumOddLengthStrings"() { 19 | expect: 20 | 8 == demo.sumOddLengthStrings() 21 | } 22 | boolean isEven(int n) { 23 | n % 2 == 0 24 | } 25 | 26 | def "SumStringsWithPredicate"() { 27 | expect: 28 | 12 == demo.sumStrings(this.&isEven) 29 | 12 == demo.sumStrings(this::isEven) 30 | 8 == demo.sumStrings { it % 2 != 0 } 31 | 8 == demo.sumStrings( n -> n % 2 != 0) 32 | 12 == demo.sumStrings(MapFilterReduce.EVENS) 33 | 8 == demo.sumStrings(MapFilterReduce.ODDS) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/groovy/streams/StreamsDemoTest.groovy: -------------------------------------------------------------------------------- 1 | package streams 2 | 3 | import org.junit.jupiter.api.Test 4 | 5 | class StreamsDemoTest { 6 | StreamsDemo demo = new StreamsDemo() 7 | 8 | @Test 9 | void joinStream() throws Exception { 10 | assert 'this is a list of strings' == demo.joinStream() 11 | } 12 | 13 | @Test 14 | void joinUpperCase() throws Exception { 15 | assert 'THIS IS A LIST OF STRINGS' == demo.joinUpperCase() 16 | } 17 | 18 | @Test 19 | void getTotalLength() throws Exception { 20 | assert demo.totalLength == 20 21 | } 22 | 23 | @Test 24 | void sumFirstNBigDecimals() throws Exception { 25 | assert 55.0d == demo.sumFirstNBigDecimals(10) 26 | assert 210.0d == demo.sumFirstNBigDecimals(20) 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/test/java/geocoder/GeocoderTest.java: -------------------------------------------------------------------------------- 1 | package geocoder; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.assertj.core.api.Assertions.assertThat; 6 | import static org.assertj.core.api.Assertions.byLessThan; 7 | import static org.junit.jupiter.api.Assertions.assertAll; 8 | 9 | public class GeocoderTest { 10 | private final Geocoder geocoder = new Geocoder(); 11 | 12 | @Test 13 | public void mosconeWest() { 14 | Location loc = new Location("Moscone West", "San Francisco", "CA"); 15 | geocoder.fillInLatLng(loc); 16 | 17 | assertAll( 18 | () -> assertThat(37.7843).isCloseTo(loc.getLatitude(), byLessThan(0.01)), 19 | () -> assertThat(-122.4007).isCloseTo(loc.getLongitude(), byLessThan(0.01)) 20 | ); 21 | } 22 | 23 | @Test 24 | public void bengaluru() { 25 | Location loc = new Location("J N Tata Auditorium", "Bangalore", "India"); 26 | geocoder.fillInLatLng(loc); 27 | 28 | assertAll( 29 | () -> assertThat(13.0134).isCloseTo(loc.getLatitude(), byLessThan(0.1)), 30 | () -> assertThat(77.56792).isCloseTo(loc.getLongitude(), byLessThan(0.1)) 31 | ); 32 | } 33 | } -------------------------------------------------------------------------------- /src/test/java/io/JumbleJavaTest.java: -------------------------------------------------------------------------------- 1 | package io; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.List; 6 | 7 | import static org.hamcrest.MatcherAssert.assertThat; 8 | import static org.hamcrest.Matchers.containsInAnyOrder; 9 | import static org.junit.jupiter.api.Assertions.assertAll; 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | 12 | class JumbleJavaTest { 13 | private final JumbleJava jumble = new JumbleJava(); 14 | 15 | @Test 16 | void checkSolver() { 17 | assertAll( 18 | () -> assertEquals(List.of("actual"), jumble.solve("cautla")), 19 | () -> assertEquals(List.of("goalie"), jumble.solve("agileo")) 20 | ); 21 | } 22 | 23 | @Test 24 | void checkParallelSolve() { 25 | List> strings = jumble.parallelSolve("zaaem", "rwdoc", "tlufan"); 26 | System.out.println(strings); 27 | assertThat(strings, containsInAnyOrder( 28 | List.of("amaze"), List.of("crowd"), List.of("flaunt", "unflat"))); 29 | System.out.println(jumble.parallelSolve("snsaoe", "craigl", "ssevur", 30 | "lonelp", "nlahed", "ceitkl")); 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/java/sorting/SortingDemoTest.java: -------------------------------------------------------------------------------- 1 | package sorting; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | import static org.junit.jupiter.api.Assertions.assertTrue; 9 | 10 | @SuppressWarnings("ResultOfMethodCallIgnored") 11 | public class SortingDemoTest { 12 | private final SortingDemo demo = new SortingDemo(); 13 | 14 | private void checkAlphabetical(List strings) { 15 | strings.stream() 16 | .reduce("", (prev, curr) -> { 17 | assertTrue(prev.compareTo(curr) <= 0); 18 | return curr; 19 | } 20 | ); 21 | } 22 | 23 | private void checkLength(List strings) { 24 | strings.stream() 25 | .reduce((prev, curr) -> { 26 | assertTrue(prev.length() <= curr.length()); 27 | return curr; 28 | } 29 | ); 30 | } 31 | 32 | @Test 33 | public void testAlphaSort() { 34 | checkAlphabetical(demo.alphaSort()); 35 | } 36 | 37 | @Test 38 | public void testAlphaSortUsingStreams() { 39 | checkAlphabetical(demo.alphaSortUsingStreams()); 40 | } 41 | 42 | @SuppressWarnings("ComparatorMethodParameterNotUsed") 43 | @Test 44 | public void testLengthReverseSortWithComparator() { 45 | List strings = demo.lengthReverseSortWithComparator().stream() 46 | .sorted((s1, s2) -> -1) 47 | .collect(Collectors.toList()); 48 | checkLength(strings); 49 | } 50 | 51 | @Test 52 | public void testLengthSortWithLambda() { 53 | checkLength(demo.lengthSortWithLambda()); 54 | } 55 | 56 | @Test 57 | public void testLengthSortUsingSorted() { 58 | checkLength(demo.lengthSortUsingSorted()); 59 | } 60 | 61 | @Test 62 | public void testLengthSortUsingComparator() { 63 | checkLength(demo.lengthSortUsingComparator()); 64 | } 65 | 66 | @Test 67 | public void testLengthSortThenAlphaSort() { 68 | demo.lengthSortThenAlphaSort().stream() 69 | .reduce((prev, curr) -> { 70 | if (prev.length() != curr.length()) { 71 | assertTrue(prev.length() <= curr.length()); 72 | } else { 73 | assertTrue(prev.compareTo(curr) <= 0); 74 | } 75 | return curr; 76 | }); 77 | } 78 | 79 | @Test 80 | public void testLengthSortThenReverseAlphaSort() { 81 | demo.lengthSortThenReverseAlphaSort().stream() 82 | .reduce((prev, curr) -> { 83 | if (prev.length() != curr.length()) { 84 | assertTrue(prev.length() <= curr.length()); 85 | } else { 86 | assertTrue(prev.compareTo(curr) >= 0); 87 | } 88 | return curr; 89 | }); 90 | } 91 | } -------------------------------------------------------------------------------- /src/test/java/streams/SumNumbersTest.java: -------------------------------------------------------------------------------- 1 | package streams; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import java.util.List; 6 | 7 | import static org.junit.jupiter.api.Assertions.*; 8 | 9 | class SumNumbersTest { 10 | @Test 11 | void getTotal() { 12 | int total = SumNumbers.getTotal( 13 | List.of(3, 1, 4, 1, 5, 9, 2, 6, 5)); 14 | assertEquals(2 * (3 + 9 + 6), total); 15 | } 16 | } -------------------------------------------------------------------------------- /src/test/kotlin/astro/AstroRequestTest.kt: -------------------------------------------------------------------------------- 1 | package astro 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import org.junit.jupiter.api.Test 5 | 6 | class AstroRequestTest { 7 | 8 | @Test 9 | fun execute() { 10 | val result = AstroRequest().execute() 11 | println(result) 12 | 13 | assertAll( 14 | { assertEquals("success", result.message) }, 15 | { assertTrue(result.number.toInt() >= 0) }, 16 | { assertEquals(result.number.toInt(), result.people.size) } 17 | ) 18 | } 19 | } -------------------------------------------------------------------------------- /src/test/kotlin/extension/PalindromeTest.kt: -------------------------------------------------------------------------------- 1 | package extension 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import org.junit.jupiter.api.Test 5 | import org.junit.jupiter.api.assertAll 6 | 7 | class PalindromeTest { 8 | @Test 9 | fun `these are palindromes (for extension function)`() { 10 | assertAll( 11 | { assertTrue("Madam, in Eden, I'm Adam".isPalindrome()) }, 12 | { assertTrue("Flee to me, remote elf!".isPalindrome()) }, 13 | { assertTrue("Sex at noon taxes".isPalindrome()) }, 14 | { assertTrue("A Santa pets rats, as Pat taps a star step at NASA".isPalindrome()) } 15 | ) 16 | } 17 | 18 | @Test 19 | internal fun `massive 543 word palindrome`() { 20 | assertTrue(""" 21 | A man, a plan, a caret, a ban, a myriad, a sum, a lac, a liar, a hoop, a pint, a catalpa, a gas, an oil, a bird, a yell, a vat, a caw, a pax, a wag, a tax, a nay, a ram, a cap, a yam, a gay, a tsar, a wall, a car, a luger, a ward, a bin, a woman, a vassal, a wolf, a tuna, a nit, a pall, a fret, a watt, a bay, a daub, a tan, a cab, a datum, a gall, a hat, a fag, a zap, a say, a jaw, a lay, a wet, a gallop, a tug, a trot, a trap, a tram, a torr, a caper, a top, a tonk, a toll, a ball, a fair, a sax, a minim, a tenor, a bass, a passer, a capital, a rut, an amen, a ted, a cabal, a tang, a sun, an ass, a maw, a sag, a jam, a dam, a sub, a salt, an axon, a sail, an ad, a wadi, a radian, a room, a rood, a rip, a tad, a pariah, a revel, a reel, a reed, a pool, a plug, a pin, a peek, a parabola, a dog, a pat, a cud, a nu, a fan, a pal, a rum, a nod, an eta, a lag, an eel, a batik, a mug, a mot, a nap, a maxim, a mood, a leek, a grub, a gob, a gel, a drab, a citadel, a total, a cedar, a tap, a gag, a rat, a manor, a bar, a gal, a cola, a pap, a yaw, a tab, a raj, a gab, a nag, a pagan, a bag, a jar, a bat, a way, a papa, a local, a gar, a baron, a mat, a rag, a gap, a tar, a decal, a tot, a led, a tic, a bard, a leg, a bog, a burg, a keel, a doom, a mix, a map, an atom, a gum, a kit, a baleen, a gala, a ten, a don, a mural, a pan, a faun, a ducat, a pagoda, a lob, a rap, a keep, a nip, a gulp, a loop, a deer, a leer, a lever, a hair, a pad, a tapir, a door, a moor, an aid, a raid, a wad, an alias, an ox, an atlas, a bus, a madam, a jag, a saw, a mass, an anus, a gnat, a lab, a cadet, an em, a natural, a tip, a caress, a pass, a baronet, a minimax, a sari, a fall, a ballot, a knot, a pot, a rep, a carrot, a mart, a part, a tort, a gut, a poll, a gateway, a law, a jay, a sap, a zag, a fat, a hall, a gamut, a dab, a can, a tabu, a day, a batt, a waterfall, a patina, a nut, a flow, a lass, a van, a mow, a nib, a draw, a regular, a call, a war, a stay, a gam, a yap, a cam, a ray, an ax, a tag, a wax, a paw, a cat, a valley, a drib, a lion, a saga, a plat, a catnip, a pooh, a rail, a calamus, a dairyman, a bater, a canal - Panama! 22 | """.trimIndent().isPalindrome()) 23 | } 24 | 25 | @Test 26 | fun `not a palindrome (for extension function)`() { 27 | assertFalse("this is not a palindrome".isPalindrome()) 28 | } 29 | 30 | 31 | @Test 32 | internal fun `these are palindromes (for function with arg)`() { 33 | assertAll( 34 | { assertTrue(isPal("Madam, in Eden, I'm Adam")) }, 35 | { assertTrue(isPal("Flee to me, remote elf!")) }, 36 | { assertTrue(isPal("A Santa pets rats, as Pat taps a star step at NASA")) } 37 | ) 38 | } 39 | 40 | @Test 41 | internal fun `not a palindrome (for function with arg)`() { 42 | assertFalse(isPal("this is not a palindrome")) 43 | } 44 | 45 | // Taken from https://speakerdeck.com/svtk/4-kotlin-types-kotlin-workshop?slide=19 46 | @Test 47 | internal fun `demonstrate replace with a string vs regex`() { 48 | assertAll( 49 | { assertEquals("one*two*", "one.two.".replace(".", "*")) }, 50 | { assertEquals("********", "one.two.".replace(".".toRegex(), "*")) } 51 | ) 52 | } 53 | } -------------------------------------------------------------------------------- /src/test/kotlin/flickr/FlickrGatewayTest.kt: -------------------------------------------------------------------------------- 1 | package flickr 2 | 3 | import kotlinx.coroutines.runBlocking 4 | import org.junit.jupiter.api.Test 5 | 6 | class FlickrGatewayTest { 7 | private val gateway = FlickrGateway() 8 | 9 | @Test // @Disabled 10 | fun `get kitties from Flickr`() { 11 | runBlocking { 12 | val flickrResult = gateway.retrofitService.getFlickrResult("kitties") 13 | println(flickrResult) 14 | for (p in flickrResult.photos.photo) { 15 | println("https://farm${p.farm}.staticflickr.com/${p.server}/${p.id}_${p.secret}.jpg") 16 | } 17 | } 18 | } 19 | 20 | @Test 21 | fun `get the images`() = runBlocking { 22 | val images = gateway.flickrResult2Image() 23 | println("There are ${images.size} images") 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/kotlin/functional/AlgorithmsKtTest.kt: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import org.hamcrest.MatcherAssert.assertThat 4 | import org.hamcrest.Matchers.`is` 5 | import org.junit.jupiter.api.* 6 | import org.junit.jupiter.api.Assertions.assertEquals 7 | import org.junit.jupiter.params.ParameterizedTest 8 | import org.junit.jupiter.params.provider.Arguments 9 | import org.junit.jupiter.params.provider.CsvSource 10 | import org.junit.jupiter.params.provider.MethodSource 11 | import java.math.BigInteger 12 | import java.util.stream.Stream 13 | 14 | @Suppress("unused") 15 | @TestInstance(TestInstance.Lifecycle.PER_CLASS) 16 | internal class AlgorithmsKtTest { 17 | private val fibData = listOf( 18 | 1 to 1, 2 to 1, 3 to 2, 19 | 4 to 3, 5 to 5, 6 to 8, 20 | 7 to 13, 8 to 21, 9 to 34, 21 | 10 to 55) 22 | 23 | companion object { 24 | // needed if parameterized test done with Lifecycle.PER_METHOD 25 | @JvmStatic 26 | fun fibs() = listOf( 27 | Arguments.of(1, 1), Arguments.of(2, 1), 28 | Arguments.of(3, 2), Arguments.of(4, 3), 29 | Arguments.of(5, 5), Arguments.of(6, 8), 30 | Arguments.of(7, 13), Arguments.of(8, 21), 31 | Arguments.of(9, 34), Arguments.of(10, 55)) 32 | 33 | @JvmStatic 34 | fun fibnumbers(): List = listOf( 35 | Arguments.of(1, 1), Arguments.of(2, 1), 36 | Arguments.of(3, 2), Arguments.of(4, 3), 37 | Arguments.of(5, 5), Arguments.of(6, 8), 38 | Arguments.of(7, 13), Arguments.of(8, 21), 39 | Arguments.of(9, 34), Arguments.of(10, 55)) 40 | 41 | @JvmStatic 42 | fun fibonacciTestData(): Stream = Stream.of( 43 | FibonacciTestData(number = 1, expected = 1), 44 | FibonacciTestData(number = 2, expected = 1), 45 | FibonacciTestData(number = 3, expected = 2), 46 | FibonacciTestData(number = 4, expected = 3), 47 | FibonacciTestData(number = 5, expected = 5), 48 | FibonacciTestData(number = 6, expected = 8), 49 | FibonacciTestData(number = 7, expected = 13) 50 | ) 51 | } 52 | 53 | 54 | @Test 55 | internal fun `Fibonacci numbers (explicit)`() { 56 | assertAll( 57 | { assertThat(fibonacci(4), `is`(3)) }, 58 | { assertThat(fibonacci(9), `is`(34)) }, 59 | { assertThat(fibonacci(2000), `is`(1392522469)) } 60 | ) 61 | } 62 | 63 | @TestFactory 64 | fun `first 10 Fibonacci numbers (dynamic)`() = 65 | fibData.map { (n, fib) -> 66 | DynamicTest.dynamicTest("fibonacci($n) == $fib") { 67 | assertThat(fibonacci(n), `is`(fib)) 68 | } 69 | } 70 | 71 | @ParameterizedTest(name = "fibonacci({0}) == {1}") 72 | @MethodSource("fibs") 73 | fun `first 10 Fibonacci numbers (companion method)`(n: Int, fib: Int) = 74 | assertThat(fibonacci(n), `is`(fib)) 75 | 76 | @ParameterizedTest(name = "fibonacci({0}) == {1}") 77 | @MethodSource("fibnumbers") 78 | fun `first 10 Fibonacci numbers (instance method)`(n: Int, fib: Int) = 79 | assertThat(fibonacci(n), `is`(fib)) 80 | 81 | @ParameterizedTest 82 | @CsvSource("1, 1", "2, 1", "3, 2", 83 | "4, 3", "5, 5", "6, 8", "7, 13", 84 | "8, 21", "9, 34", "10, 55") 85 | fun `first 10 Fibonacci numbers (csv)`(n: Int, fib: Int) = 86 | assertThat(fibonacci(n), `is`(fib)) 87 | 88 | @ParameterizedTest 89 | @MethodSource("fibonacciTestData") 90 | fun `check fibonacci using data class`(data: FibonacciTestData) { 91 | assertThat(fibonacci(data.number), `is`(data.expected)) 92 | } 93 | 94 | 95 | @ParameterizedTest 96 | @MethodSource("fibonacciTestData") 97 | fun `check fibonacci with fold`(data: FibonacciTestData) { 98 | assertThat(fibonacciFold(data.number), `is`(data.expected)) 99 | } 100 | 101 | @Test 102 | fun `watch fibonacci fold in action`() { 103 | val total = fibonacciFoldDebug(10) 104 | println("Fib(10) == $total") 105 | } 106 | 107 | @Test 108 | //@Disabled("slow") 109 | internal fun `factorial tests`() { 110 | assertAll( 111 | { assertThat(factorial(0), `is`(BigInteger.ONE)) }, 112 | { assertThat(factorial(1), `is`(BigInteger.ONE)) }, 113 | { assertThat(factorial(2), `is`(BigInteger.valueOf(2))) }, 114 | { assertThat(factorial(5), `is`(BigInteger.valueOf(120))) }, 115 | { assertThat(factorial(15000).toString().length, `is`(56130)) }, 116 | { assertThat(factorial(75000).toString().length, `is`(333061)) } 117 | ) 118 | } 119 | 120 | @Test 121 | internal fun `check recursive factorial`() { 122 | assertAll( 123 | { assertThat(recursiveFactorial(0), `is`(BigInteger.ONE)) }, 124 | { assertThat(recursiveFactorial(1), `is`(BigInteger.ONE)) }, 125 | { assertThat(recursiveFactorial(2), `is`(BigInteger.valueOf(2))) }, 126 | { assertThat(recursiveFactorial(5), `is`(BigInteger.valueOf(120))) }, 127 | { assertThrows { recursiveFactorial(20_000) } } 128 | ) 129 | } 130 | 131 | @Test 132 | //@Disabled("slow") 133 | internal fun `folding factorial tests`() { 134 | assertAll( 135 | { assertThat(factorialFold(0), `is`(BigInteger.ONE)) }, 136 | { assertThat(factorialFold(1), `is`(BigInteger.ONE)) }, 137 | { assertThat(factorialFold(2), `is`(BigInteger.valueOf(2))) }, 138 | { assertThat(factorialFold(5), `is`(BigInteger.valueOf(120))) }, 139 | { assertThat(factorialFold(15000).toString().length, `is`(56130)) }, 140 | { assertThat(factorialFold(75000).toString().length, `is`(333061)) } 141 | ) 142 | } 143 | 144 | @Test 145 | internal fun `sum using fold`() { 146 | val numbers = intArrayOf(3, 1, 4, 1, 5, 9) 147 | assertEquals(numbers.sum(), sum(*numbers)) 148 | } 149 | 150 | @Test 151 | internal fun `sum using fold with trace`() { 152 | val numbers = intArrayOf(3, 1, 4, 1, 5, 9) 153 | assertEquals(numbers.sum(), sumWithTrace(*numbers)) 154 | } 155 | 156 | @Test 157 | internal fun `sum using reduce`() { 158 | val numbers = intArrayOf(3, 1, 4, 1, 5, 9) 159 | assertAll( 160 | { assertEquals(numbers.sum(), sumReduce(*numbers)) }, 161 | { assertThrows { sumReduce() } } 162 | ) 163 | } 164 | 165 | @Test 166 | internal fun `sum using reduce doubles`() { 167 | val numbers = intArrayOf(3, 1, 4, 1, 5, 9) 168 | // first value is not doubled! 169 | assertEquals(numbers.sum() * 2 - 3, sumReduceDoubles(*numbers)) 170 | } 171 | } 172 | 173 | data class FibonacciTestData(val number: Int, val expected: Int) 174 | -------------------------------------------------------------------------------- /src/test/kotlin/functional/PrimesTest.kt: -------------------------------------------------------------------------------- 1 | package functional 2 | 3 | import org.junit.jupiter.api.Assertions.* 4 | import org.junit.jupiter.api.Test 5 | import org.junit.jupiter.api.TestInstance 6 | import org.junit.jupiter.params.ParameterizedTest 7 | import org.junit.jupiter.params.provider.MethodSource 8 | import org.junit.jupiter.params.provider.ValueSource 9 | import kotlin.system.measureTimeMillis 10 | 11 | data class NextPrimeTestData(val number: Int, val expected: Int) 12 | 13 | @TestInstance(TestInstance.Lifecycle.PER_CLASS) 14 | internal class PrimesTest { 15 | companion object { 16 | @JvmStatic 17 | fun nextPrimeTestData() = listOf( 18 | NextPrimeTestData(2, 3), 19 | NextPrimeTestData(3, 5), 20 | NextPrimeTestData(4, 5), 21 | NextPrimeTestData(5, 7), 22 | NextPrimeTestData(6, 7), 23 | NextPrimeTestData(7, 11), 24 | NextPrimeTestData(182, 191), 25 | NextPrimeTestData(9973, 10007) 26 | ) 27 | } 28 | 29 | @ParameterizedTest(name = "{0} is prime and less than 20") 30 | @ValueSource(ints = [2, 3, 5, 7, 11, 13, 17, 19]) 31 | internal fun `primes less than 20`(n: Int) { 32 | assertTrue(n.isPrime()) 33 | } 34 | 35 | @ParameterizedTest(name = "{0} is composite and less than or equal to 20") 36 | @ValueSource(ints = [4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20]) 37 | internal fun `composites less than or equal to 20`(n: Int) { 38 | assertFalse(n.isPrime()) 39 | } 40 | 41 | @ParameterizedTest 42 | @MethodSource("nextPrimeTestData") 43 | fun `check isPrime values using data class`(data: NextPrimeTestData) { 44 | assertEquals(data.expected, nextPrime(data.number)) 45 | } 46 | 47 | @Test 48 | internal fun `first 10 primes`() { 49 | val primes = firstNPrimes(10) 50 | // .also(::println) 51 | assertEquals(10, primes.size) 52 | assertEquals(listOf(2, 3, 5, 7, 11, 13, 17, 19, 23, 29), primes) 53 | } 54 | 55 | @Test 56 | internal fun `first 1000 primes`() { 57 | val time = measureTimeMillis { 58 | val primes = firstNPrimes(10_000) 59 | println("${primes.size} prime numbers generated (the last one is ${primes.last()})") 60 | } 61 | println("Algorithm took ${time}ms") 62 | } 63 | 64 | @Test 65 | internal fun `find all primes less than 20`() { 66 | primesLessThan(20) 67 | .also(::println) 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/test/kotlin/io/JumbleKotlinTest.kt: -------------------------------------------------------------------------------- 1 | package io 2 | 3 | import org.junit.jupiter.api.Assertions.assertEquals 4 | import org.junit.jupiter.api.Test 5 | import org.junit.jupiter.api.assertAll 6 | import org.junit.jupiter.params.ParameterizedTest 7 | import org.junit.jupiter.params.provider.CsvSource 8 | 9 | class JumbleKotlinTest { 10 | private val jumbleKotlin: JumbleKotlin = JumbleKotlin() 11 | 12 | @Test 13 | fun `check solver`() { 14 | assertAll( 15 | { assertEquals("actual", jumbleKotlin.solve("cautla")[0]) }, 16 | { assertEquals("goalie", jumbleKotlin.solve("agileo")[0]) }, 17 | { assertEquals("mumble", jumbleKotlin.solve("mmlueb")[0]) } 18 | ) 19 | } 20 | 21 | @ParameterizedTest(name = "{0} unscrambles to {1}") 22 | @CsvSource("cautla, actual", 23 | "agileo, goalie", "mmlueb, mumble") 24 | fun `unscramble words`(clue: String, answer: String) = 25 | assertEquals(jumbleKotlin.solve(clue)[0], answer) 26 | 27 | @Test 28 | internal fun `check solveAll`() { 29 | assertEquals(listOf("actual", "goalie", "mumble"), 30 | jumbleKotlin.solveAll("cautla", "agileo", "mmlueb").map { it[0] }) 31 | } 32 | } -------------------------------------------------------------------------------- /src/test/kotlin/sequences/SumNumbersTest.kt: -------------------------------------------------------------------------------- 1 | package sequences 2 | 3 | import org.junit.jupiter.api.Assertions.assertEquals 4 | import org.junit.jupiter.api.Test 5 | import org.junit.jupiter.api.assertAll 6 | 7 | internal class SumNumbersTest { 8 | 9 | @Test 10 | fun `total should be 36`() { 11 | assertAll( 12 | { assertEquals(36, getTotal(listOf(3, 1, 4, 1, 5, 9, 2, 6, 5))) }, 13 | { assertEquals(36, getTotalUsingSequences(listOf(3, 1, 4, 1, 5, 9, 2, 6, 5))) } 14 | ) 15 | } 16 | } --------------------------------------------------------------------------------