├── .gitignore ├── README.md ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src └── main └── kotlin └── day_1_kotlin ├── langeng ├── assignments │ ├── KotlinWorkshop1.kt │ ├── KotlinWorkshop2.kt │ ├── KotlinWorkshop3.kt │ ├── KotlinWorkshop4.kt │ ├── KotlinWorkshop5.kt │ ├── KotlinWorkshop6.kt │ ├── KotlinWorkshop7.kt │ ├── KotlinWorkshop8.kt │ └── KotlinWorkshop9.kt ├── info │ ├── A_HowToComment.kt │ ├── B_HowToRunProgram.kt │ ├── C_HowToPrintResults.kt │ └── D_HowToUseHotkeys.kt └── solutions │ ├── KotlinWorkshop1.kt │ ├── KotlinWorkshop2.kt │ ├── KotlinWorkshop3.kt │ ├── KotlinWorkshop4.kt │ ├── KotlinWorkshop5.kt │ ├── KotlinWorkshop6.kt │ ├── KotlinWorkshop7.kt │ ├── KotlinWorkshop8.kt │ └── KotlinWorkshop9.kt └── langrus ├── assignments ├── KotlinWorkshop1.kt ├── KotlinWorkshop2.kt ├── KotlinWorkshop3.kt ├── KotlinWorkshop4.kt ├── KotlinWorkshop5.kt ├── KotlinWorkshop6.kt ├── KotlinWorkshop7.kt ├── KotlinWorkshop8.kt └── KotlinWorkshop9.kt ├── info ├── A_HowToComment.kt ├── B_HowToRunProgram.kt ├── C_HowToPrintResults.kt └── D_HowToUseHotkeys.kt └── solutions ├── KotlinWorkshop1.kt ├── KotlinWorkshop2.kt ├── KotlinWorkshop3.kt ├── KotlinWorkshop4.kt ├── KotlinWorkshop5.kt ├── KotlinWorkshop6.kt ├── KotlinWorkshop7.kt ├── KotlinWorkshop8.kt └── KotlinWorkshop9.kt /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /build/ 3 | /.gradle/ 4 | /local.properties 5 | *.iml 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 2020-Fundamentals-Kotlin 2 | 3 | Tasks for the first Android Academy Fundamentals course. 4 | 5 | Package `assignments` contains tasks divided in workshop files. 6 | 7 | Package `solutions` contains... solutions! :) 8 | 9 | Package `info` contains simple help for students: how to comment, run and print code. 10 | 11 | Packages grouped by languages: `langeng` contains workshops with description in English, `langrus` in Russian. Content is similar. 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'org.jetbrains.kotlin.jvm' version '1.3.72' 3 | } 4 | 5 | group 'org.example' 6 | version '1.0-SNAPSHOT' 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation "org.jetbrains.kotlin:kotlin-stdlib" 14 | } 15 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Android-Academy-Global/2020-Fundamentals-Kotlin/3f58ff4132dca0365b0bf2c5be5a808e747ea5a9/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /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 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /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 Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | 88 | @rem Execute Gradle 89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 90 | 91 | :end 92 | @rem End local scope for the variables with windows NT shell 93 | if "%ERRORLEVEL%"=="0" goto mainEnd 94 | 95 | :fail 96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 97 | rem the _cmd.exe /c_ return code! 98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 99 | exit /b 1 100 | 101 | :mainEnd 102 | if "%OS%"=="Windows_NT" endlocal 103 | 104 | :omega 105 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'AndroidAcademyKotlin' 2 | 3 | -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop1.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf", 7 | "RedundantNullableReturnType", 8 | "RedundantExplicitType", 9 | "unused" 10 | ) 11 | 12 | package day_1_kotlin.langeng.assignments 13 | 14 | import java.util.* 15 | 16 | // Workshop #1 - val, var, null, kotlin null safety, Elvis operator 17 | 18 | object KotlinWorkshop1 { 19 | 20 | @JvmStatic 21 | fun main(args: Array) { 22 | 23 | // Initializing variables. Pay attention - it's nullable! 24 | // Don't touch! Given: 25 | val nullableElvisString: String? = null 26 | val nullableAssertionString: String? = "potentially null" 27 | val emptyString = "" 28 | 29 | 30 | 31 | /* Exercise area */ 32 | 33 | // TODO 1: Uncomment. 34 | // Assign "nullableElvisString" to the "notNullUserString" and fix the assignment with elvis operator. 35 | // If "nullableElvisString" is null, "notNullUserString" should be equal to "emptyString". 36 | // var notNullUserString: String = 37 | // println("Result string is empty $notNullUserString") 38 | 39 | // TODO 2: Uncomment. 40 | // We know that "nullableString" is non-null by fact. Reassign value from "nullableAssertionString" using !! operator. 41 | // notNullUserString = 42 | // println("Result string is $notNullUserString") 43 | 44 | 45 | 46 | /* Exercise bonus area */ 47 | 48 | // TODO 3: Uncomment. Assign a sum of two numbers to "sum". 49 | // If first number is null, result should be null. If second one is null, result should be equal to first number. 50 | // Use '?' check, '.plus()' function and '?:' to add valid alternative inside '.plus()'. 51 | val notNullAlternative = 0 52 | val firstNumber: Int? = 10 53 | val secondNumber: Int? = 20 54 | // val sum : Int? = 55 | // println("Sum is {$sum}") 56 | 57 | 58 | // TODO 4: Uncomment. Store user String input in a "stringInput" variable. 59 | // While running the program. Look at the console. Click inside the console area. Input a string. 60 | // print("Please, input a string: ") 61 | // val stringInput: String? = MyScanner.scan.next() // <--- string input 1 62 | 63 | // TODO 5: Uncomment. 64 | // Store user Int input in "firstIntInput" and "secondIntInput" variables. 65 | // Replace the 'null' to calculate a "sumIntInputs". 66 | // Use '?' check, '.plus()' function and '?:' to add valid alternative inside '.plus()'. 67 | // While running the program. Look at the console. Click inside the console area. Input a number, then second number. 68 | // print("Please, input a number: ") 69 | // val firstIntInput: Int? = MyScanner.scan.nextInt() // <--- number input 1 70 | // print("Please, input a second number: ") 71 | // val secondIntInput: Int? = MyScanner.scan.nextInt() // <--- number input 2 72 | // val sumIntInputs : Int? = firstIntInput?.plus(secondIntInput ?: null) // <--- replace 'null' with correct expression 73 | // println("String:$stringInput, Sum of numbers:$sumIntInputs") 74 | 75 | 76 | 77 | /* Examples area */ 78 | 79 | val number: Int = -1 80 | val someNumber: Double = 2.5 81 | val someString: String = "Hello world" 82 | val someFlag: Boolean = true 83 | var someNullableNumber: Long? = null 84 | } 85 | } 86 | 87 | 88 | 89 | /* DO NOT TOUCH the utils below. */ 90 | 91 | class MyScanner { 92 | companion object { 93 | val scan = Scanner(System.`in`) 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop2.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf", 7 | "RedundantNullableReturnType", 8 | "RedundantExplicitType", 9 | "unused" 10 | ) 11 | 12 | package day_1_kotlin.langeng.assignments 13 | 14 | import java.util.* 15 | import kotlin.random.Random 16 | 17 | // Workshop #2 - control flow (if, when), arrays, for loop, if expression, return & jumps 18 | 19 | object KotlinWorkshop2 { 20 | 21 | // You can run the main function to test the code 22 | @JvmStatic 23 | fun main(args: Array) { 24 | 25 | 26 | 27 | /* Exercise area */ 28 | 29 | // Initializing variables in runtime with input. 30 | // While running the program. Look at the console. Click inside the console window. Input a number. 31 | // Don't touch! Given: 32 | val upperBound = getUpperBound() 33 | val nonNullUpperBound = upperBound ?: 10 34 | val randomNumber = Random.nextInt(nonNullUpperBound) 35 | val scanner = Scanner(System.`in`) 36 | 37 | while (true) { 38 | // TODO 1: Add logic for comparing userInput with randomNumber with If-Else operator. 39 | // Break infinite while loop when user input correct number. Show message "Congratulations" 40 | // If user entered number below randomNumber - show message "Your Guess is Lower" 41 | // if user entered number over randomNumber - show message "Your Guess is Higher" 42 | 43 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 44 | // Storing user input in userInput variable 45 | // While running the program. Look at the console. Click inside the console window. Input a number. 46 | val userInput: Int = scanner.nextInt() 47 | if (true) { 48 | 49 | } 50 | } 51 | 52 | 53 | 54 | /* Exercise bonus area */ 55 | 56 | // TODO 2: Uncomment. Initialize "numbersArray". 57 | // It should be an array of Int with capacity = 5. 58 | // val numbersArray = 59 | 60 | // TODO 3: Uncomment. Initialize "size". 61 | // Change infinite while-loop condition. Limit user input with a size of "numbersArray". 62 | println("\nTraining 2. \"Fill in the collection\"") 63 | // val size = 64 | var counter = 0 65 | while (true) { 66 | print("Input a number in range 0..10 inclusive: ") 67 | val userInput: Int = scanner.nextInt() 68 | 69 | // TODO 4: Add inputs to the "numbersArray" using the following logic: 70 | // if userInput is 3 - add this 3 number "as is". 71 | // if userInput is 5 - add 5 * size of numbersArray. 72 | // if userInput is 9 - add 2 + size of numbersArray. 73 | // else don't add anything. 74 | // Use "When" operator. 75 | when { 76 | 77 | } 78 | 79 | counter++ 80 | } 81 | 82 | // TODO 5: Print line by line elements of numbersArray with their indexes. 83 | // Should looks like "index value". 84 | 85 | } 86 | 87 | 88 | 89 | /* DO NOT TOUCH the utils below. */ 90 | 91 | private fun getUpperBound(): Int? { 92 | println("Training 1. \"Guess a number\"") 93 | print("Enter maximum number in range 10..20 inclusive: ") 94 | val scanner = Scanner(System.`in`) 95 | return try { 96 | scanner.nextInt() 97 | 98 | } catch (e: InputMismatchException) { 99 | null 100 | } 101 | } 102 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop3.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("CanBeVal", "UNUSED_PARAMETER", "unused", "UNUSED_VARIABLE", "UNUSED_ANONYMOUS_PARAMETER") 2 | 3 | package day_1_kotlin.langeng.assignments 4 | 5 | import java.util.* 6 | import java.util.logging.Logger 7 | import kotlin.random.Random 8 | 9 | // Workshop #3 - functions, lambda, high-order function 10 | 11 | object KotlinWorkshop3 { 12 | 13 | // You can run the main function to test the code 14 | @JvmStatic 15 | fun main(args: Array) { 16 | // Initializing variables in runtime with input. 17 | // While running the program. Look at the console. Click inside the console window. Input a number. 18 | // Don't touch! Given: 19 | val scanner = Scanner(System.`in`) 20 | val upperBound = getUpperBound(scanner) 21 | val nonNullUpperBound = upperBound ?: 10 22 | val randomNumber = Random.nextInt(nonNullUpperBound) 23 | val capacity = nonNullUpperBound 24 | val guesses = createIntArrayOfCapacity(capacity) 25 | 26 | 27 | 28 | /* Exercise area */ 29 | 30 | var guessed = false 31 | var counter = 0 32 | while (!guessed && counter < capacity) { 33 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 34 | // Storing user input in userInput variable 35 | // While running the program. Look at the console. Click inside the console window. Input a number. 36 | val userInput: Int = getNextInput(scanner, nonNullUpperBound) 37 | guesses[counter] = userInput 38 | 39 | // TODO 1: Uncomment. Declare playRound function: takes 2 integer arguments and returns a boolean. 40 | // guessed = playRound(userInput, randomNumber) 41 | 42 | counter++ 43 | } 44 | 45 | // TODO (bonus): Create analytics system for the game. Collect stats and print. 46 | printGameStats(guesses, counter, randomNumber) 47 | } 48 | 49 | // TODO 1: Uncomment. Declare playRound function: takes 2 integer arguments and returns a boolean. 50 | // TODO 2: Add logic for comparing userInput with randomNumber with If-Else operator. 51 | // Break infinite while loop when user input correct number. Show message "Congratulations" 52 | // If user entered number below randomNumber - show message "Your Guess is Lower" 53 | // if user entered number over randomNumber - show message "Your Guess is Higher". 54 | // See workshop #2 55 | // private fun playRound(...) : ... { 56 | // 57 | // return false 58 | // } 59 | 60 | 61 | 62 | /* Exercise bonus area */ 63 | 64 | // TODO (bonus): Create analytics system for the game. Collect stats and print. 65 | private fun printGameStats(guesses: IntArray, guessCounter: Int, randomNumber: Int) { 66 | // TODO 3: Uncomment. Print total guesses count. 67 | // printTotalCountOfGuesses(guessCounter) 68 | 69 | // TODO 4: Uncomment. 70 | // Add high level function "countHigherGuesses" for printing higher elements from array. 71 | // countHigherGuesses(guesses, randomNumber) { counter -> 72 | // println("Total count of higher guesses: $counter\n") 73 | // } 74 | 75 | // TODO 5: Uncomment. Create lambda function "countLowerGuesses" for printing lower elements from array. 76 | // Do not print element if its value == "-1", the default value given to array on a initializing stage. 77 | // countLowerGuesses(guesses, randomNumber) 78 | 79 | // TODO 6: Uncomment. Print every element of guesses in separate line via .forEach high-level function. 80 | // guesses 81 | } 82 | 83 | // TODO 3 84 | // Should print total guesses count. 85 | private fun printTotalCountOfGuesses(guessCounter: Int) { 86 | TODO() 87 | } 88 | 89 | // TODO 4 90 | // Should count and print guesses that were higher than randomNumber. 91 | // Should return count as fun result. 92 | private fun countHigherGuesses( 93 | guesses: IntArray, 94 | randomNumber: Int, 95 | printer: (Int) -> Unit 96 | 97 | ): Int { 98 | var counter = 0 99 | TODO() 100 | } 101 | 102 | // TODO 5 103 | // Should count and print guesses that were lower than randomNumber. 104 | val countLowerGuesses: (IntArray, Int) -> Unit = { guesses, randomNumber -> 105 | TODO() 106 | } 107 | 108 | 109 | 110 | /* DO NOT TOUCH the utils below. */ 111 | 112 | private fun getUpperBound(scanner: Scanner): Int? { 113 | val upperLimit = 20 114 | val lowerLimit = 1 115 | 116 | println("Game: \"Guess a number\"") 117 | print("Enter maximum number in range 1..20 inclusive: ") 118 | return try { 119 | var input = scanner.nextInt() 120 | if (input in lowerLimit..upperLimit) { 121 | input 122 | 123 | } else { 124 | println("Wrong number. Use default as limit: $upperLimit") 125 | upperLimit 126 | } 127 | 128 | } catch (e: InputMismatchException) { 129 | null 130 | } 131 | } 132 | 133 | private fun getNextInput(scanner: Scanner, nonNullUpperBound: Int): Int { 134 | val lowerLimit = 0 135 | val badResult = -1 136 | 137 | return try { 138 | var input = scanner.nextInt() 139 | if (input in lowerLimit..nonNullUpperBound) { 140 | input 141 | 142 | } else { 143 | println("Wrong input. Should be $nonNullUpperBound or lower.") 144 | badResult 145 | } 146 | 147 | } catch (e: InputMismatchException) { 148 | val log = Logger.getLogger("KotlinWorkshop3Logger") 149 | log.throwing("KotlinWorkshop3Logger", "getNextInput()", e) 150 | badResult 151 | } 152 | } 153 | 154 | private fun createIntArrayOfCapacity(capacity: Int): IntArray { 155 | return IntArray(capacity) { i -> -1 } 156 | } 157 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop4.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.assignments 2 | 3 | // Workshop #4 - classes 4 | 5 | object KotlinWorkshop4 { 6 | 7 | // Don't touch! Given: 8 | @JvmStatic 9 | fun main(args: Array) { 10 | testBus() 11 | } 12 | 13 | 14 | 15 | /* Exercise area */ 16 | 17 | // ? Classes should be declared in the bottom of a file. Below functions. 18 | // There is an exception. We sort declarations by TODOs. 19 | // TODO 1: Declare a class Bus that will have integer amount of "passengersCount" as a property. 20 | // class ...(...) { 21 | 22 | // TODO 2: Add method "drive" without arguments that will print "Driving n passengers to the destination" 23 | // where n - count of passengers. 24 | // fun drive() { 25 | // println("Drive on car") 26 | // } 27 | // } 28 | 29 | private fun testBus() { 30 | // TODO 3: Create an instance of your class. 31 | // val bus = ... 32 | 33 | // TODO 4: Drive your bus to the destination and check out that the output is correct. 34 | // ... .drive() 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop5.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package day_1_kotlin.langeng.assignments 4 | 5 | // Workshop #5 - inheritance, abstract, interface 6 | 7 | // Don't touch! Given: 8 | // Declare a contract for a transport ability. 9 | interface Driveable { 10 | fun drive() 11 | } 12 | 13 | // Declare a transport class which describes passenger transport of all types. 14 | // Give this transport an ability to drive. 15 | abstract class Transport(protected var passengersCount: Int): Driveable 16 | 17 | // Create a Bicycle transport which can carry a single person. 18 | class Bicycle: Transport(1) { 19 | override fun drive() { 20 | println("Ride a bicycle.") 21 | } 22 | } 23 | 24 | 25 | 26 | /* Exercise area */ 27 | 28 | // TODO 1: Create a new interface that will be appropriate for new classes below. 29 | // ? By convention, names of Classes and Interfaces start with an upper case letter and use the camel case. 30 | // Example: "SomeLongClassName". 31 | //interface ... 32 | 33 | // TODO 2: Write your own class Bus and some Car. 34 | // Instead of writing it from scratch, extend it from the Transport class and your new interface. 35 | // ? Class can extends only one other class, but implements many interfaces, i.e.: 36 | // class Kitty(): Cat, Cuteable, Sleepable, Furryable {} 37 | 38 | //class Bus ... 39 | //class Car ... 40 | 41 | // TODO 3: Test your transport in appropriate sections 42 | object VehiclesTest { 43 | 44 | // You can run the main function to test the code 45 | @JvmStatic 46 | fun main(args: Array) { 47 | testBus() 48 | testCar() 49 | testBicycle() 50 | } 51 | 52 | private fun testBus() { 53 | println("Testing how bus drives...") 54 | // val bus = ... 55 | } 56 | 57 | private fun testCar() { 58 | println("Testing how car drives...") 59 | // val car = ... 60 | } 61 | 62 | private fun testBicycle() { 63 | println("Testing how bicycle drives...") 64 | // ... 65 | } 66 | 67 | 68 | 69 | /* Exercise bonus area */ 70 | 71 | // TODO 4: Test bus abilities as separate features. 72 | private fun testBusParts() { 73 | println("Testing bus's feature 1...") 74 | 75 | 76 | println("Testing bus's feature 2...") 77 | 78 | } 79 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop6.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.assignments 2 | 3 | // Workshop #6 - special classes, objects, data classes 4 | 5 | 6 | 7 | /* Exercise area */ 8 | 9 | // TODO 1: Add 2-4 properties to the data class 10 | // data class VideoGame(...) 11 | 12 | // TODO 2: Create on object that will be used to test the games, call it "VideoGamesTest". 13 | // ... VideoGamesTest { 14 | 15 | // Uncomment after declaring an object. 16 | // @JvmStatic 17 | // fun main(args: Array) { 18 | // TODO 3: Create an instance of VideoGame. 19 | // Make a copy via .copy() method and store the copy to another variable. 20 | // val game = 21 | // val copy = 22 | 23 | // TODO 4: Print out if those data class objects are equal. 24 | // Use "==" to compare. Should be true. 25 | // val equal = false 26 | // println("Objects are equal $equal") 27 | 28 | // TODO 5: Put several data class objects into an array and print them out. 29 | // val games = arrayOf(game, copy, ...) 30 | // games.forEach { 31 | // // print 32 | // } 33 | // } 34 | //} 35 | 36 | 37 | 38 | /* Exercise bonus area */ 39 | 40 | // TODO 6: Create an enum class Genre with a few values, and add it as a field to the VideoGame. 41 | // Fix created video game instances in the main() function and run main(). 42 | /* 43 | ... Genre { 44 | ..., 45 | ..., 46 | ... 47 | } 48 | * */ 49 | 50 | // TODO 7: Add a new property to the VideoGame class with default value. 51 | // As you can see, you don't have to fix already created instances. 52 | // But you have to remember that this can change a behaviour of instances in some cases. 53 | // Run program and see new print results. -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop7.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_VARIABLE") 2 | 3 | package day_1_kotlin.langeng.assignments 4 | 5 | // Workshop #7 - list, mutable list, useful functions, maps 6 | object KotlinWorkshop7 { 7 | 8 | @JvmStatic 9 | fun main(args: Array) { 10 | 11 | // Don't touch! Given: 12 | val sadPoem = arrayOf( 13 | "True happiness can be attained", 14 | "Only if one's surroundings are good.", 15 | "It's not true that good exists", 16 | "I'm sure you can agree that", 17 | "The reality", 18 | "Creates", 19 | "My attitude", 20 | "It's all beyond my control", 21 | "And you'll never in a million years hear me say that", 22 | "Today was a very good day." 23 | ) 24 | 25 | 26 | /* Exercise area */ 27 | 28 | // TODO 1: Print the "poem" for 2 cases: 29 | // 1. Filter and print lines shorter than 12 symbols; 30 | // 2. Print poem reversed. 31 | /* 32 | val filtered = ... 33 | val reversed = ... 34 | println(filtered) 35 | println(reversed) 36 | * */ 37 | 38 | // TODO 2: Uncomment. 39 | // Initialize an evenList variable and add to it only "even" numbers from 0 to 50. 40 | /* 41 | val evenList = ... 42 | for (i in 0..50) { 43 | } 44 | println(evenList) 45 | */ 46 | 47 | 48 | 49 | 50 | // Don't touch! Given: 51 | val weatherMap = mutableMapOf( 52 | "Moscow" to 2, 53 | "St. Petersburg" to -1, 54 | "Minsk" to 4 55 | ) 56 | 57 | 58 | 59 | /* Exercise bonus area */ 60 | 61 | // TODO 3. Add a weather for Kiev and Tel-Aviv to weatherMap. 62 | // weatherMap... = 63 | 64 | // TODO 4. Filter and print cities with temperature of zero+. 65 | // Connect operators as a chain. 66 | // weatherMap 67 | } 68 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop8.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("MayBeConstant", "unused", "UNUSED_VARIABLE") 2 | 3 | package day_1_kotlin.langeng.assignments 4 | // workshop #8 - const, companion object, extension func* 5 | 6 | /* 7 | * Сокращаем телефон до максимально докустимой длины maxLength 8 | * и пишем функцию экстеншен на лист, которая заменяет каждый i-й элемент номером телефона 9 | */ 10 | 11 | // TODO 1: make maxLength const that is visible only inside the Person class 12 | val maxLength = 12 13 | 14 | // TODO 2: make companionConstant part of companion object 15 | val companionConstant = 12 16 | 17 | class Person(phoneCode: String) { 18 | 19 | val code = if (phoneCode.length > maxLength) phoneCode.subSequence(0, maxLength) else phoneCode 20 | 21 | companion object { 22 | // TODO 2 23 | } 24 | 25 | // * * * Bonus task * * * (work on home) 26 | 27 | //TODO 3: make this fun as extension to a list outside the Person class 28 | private fun replacePlacesWithThePhoneCode(list: List, placeNum: Int = 3): List { 29 | return list.mapIndexed { index, any -> if (index % placeNum == 0) code else any} 30 | } 31 | } 32 | 33 | fun main(){ 34 | val list = mutableListOf("1", 3, 4, "Patrick", 3.4, "123-59") 35 | 36 | val p = Person("45-45-45") 37 | 38 | 39 | // TODO: uncomment after finishing TODO 1 40 | // println(Person.maxLength) 41 | 42 | //TODO *: uncomment after doing function 43 | // lst.replacePlacesWithThePhoneCode(p, 4) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/assignments/KotlinWorkshop9.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package day_1_kotlin.langeng.assignments 4 | 5 | // workshop #9 - generics 6 | /* 7 | * Класс программиста, который может учить и забывать концепты на определенном языке. 8 | */ 9 | 10 | fun main() { 11 | val p = Programmer() 12 | 13 | //TODO: uncomment all 14 | // p.learn(Kotlin("basics")) 15 | // 16 | // p.learn(Kotlin("generics")) 17 | // p.learn(Kotlin("coroutines")) 18 | 19 | println(p.howManyConceptsDoIKnow()) 20 | // should be equal to 3 21 | 22 | println(p.lastConcept()) 23 | //should be Kotlin(element=coroutines) 24 | 25 | // p.forget(Kotlin("generics")) 26 | println(p.howManyConceptsDoIKnow()) 27 | // should be equal to 2 28 | } 29 | 30 | 31 | class Programmer { 32 | 33 | fun howManyConceptsDoIKnow(): Int = TODO() 34 | 35 | // TODO: add "learn" function with new concept 36 | 37 | //TODO: add "forget" function with one concept to forget 38 | 39 | fun lastConcept(): T = TODO() 40 | } 41 | 42 | interface Language{ 43 | val element: String 44 | } 45 | 46 | data class JavaLanguage(override val element: String) : Language 47 | data class Kotlin(override val element: String): Language 48 | data class Swift(override val element: String): Language 49 | data class C_Sharp(override val element: String): Language 50 | -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/info/A_HowToComment.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.info 2 | 3 | /** 4 | * This is Class java-doc. 5 | * Place cursor onto the class name [A_HowToComment] and press ctrl+Q. 6 | * You may comment classes, functions, etc. 7 | */ 8 | object A_HowToComment { 9 | 10 | // Commented code ignored by compiler. 11 | 12 | // How to comment: 13 | 14 | // 1. Use double slash in the beginning of the string. One line comment: 15 | // val commented = "ignored" 16 | // Place cursor on any position in the line 17 and press Ctrl+/ 17 | val plzCommentMe = "null" 18 | 19 | // 2. Surround part of code with /**/ 20 | val commented = /*"ignored"*/ "not ignored" 21 | 22 | // 3a. Surround multiple lines with /**/ 23 | /* 24 | * val firstLine = "ignored" 25 | * val secondLine = "ignored" 26 | * */ 27 | 28 | // 3b. Or like this: 29 | /* 30 | val firstLine = "ignored" 31 | val secondLine = "ignored" 32 | */ 33 | 34 | // 4. These are common reserved words to highlight tasks: 35 | // TODO 36 | // FIXME 37 | // i.e. FIXME AuthorName 10/26/2020: have to refactor something 38 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/info/B_HowToRunProgram.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.info 2 | 3 | object B_HowToRunProgram { 4 | 5 | // The entry point of your code is a "main" function with reserved syntax. 6 | // It is a static function. 7 | 8 | // If you start code in an empty file, start typing "ma", end wait. 9 | // The intellij idea will suggest you the auto-completion with shortcut "maino". 10 | 11 | // When you see a suggestion, just press "Enter": 12 | @JvmStatic 13 | fun main(args: Array) { 14 | // You may Build and Run program with "Ctrl+Shift+F10". 15 | // Or by clicking a green triangle to the left side of the code. See line 13. 16 | } 17 | 18 | // You may run code for a test purposes without writing the "main" function. 19 | // Start Kotlin test environment: in the main menu find "Tools -> Kotlin -> Kotlin REPL". 20 | // Click in the opened console window. Type your code, press "Ctrl+Enter" to run. 21 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/info/C_HowToPrintResults.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.info 2 | 3 | import java.util.logging.Logger 4 | 5 | object C_HowToPrintResults { 6 | 7 | // To see results in the console use some Standard output and/or logger classes in the Sdk. 8 | // Functions print(), println() or logger. 9 | 10 | // Console is in the "Run" tab. In the bottom menu of the Intellij idea. 11 | 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println("message") // A string 15 | println("message " + "other") // A concatenation of strings 16 | println("message " + 1) // A concatenation of different objects 17 | 18 | val value = "value" 19 | println("message $value") // A placeholder 20 | 21 | println("message ${Results().property}") // A placeholder with calculated result 22 | 23 | println("message value:" + value + ", property:${Results().property}") 24 | 25 | println(""" 26 | |long 27 | |formatted 28 | |message 29 | """.trimIndent()) 30 | 31 | try { 32 | // Code with error 33 | } catch (expected: Exception) { 34 | val log = Logger.getLogger("MyWorkshopLogger") 35 | log.throwing("Current class name", "someMethod()", expected) 36 | } 37 | } 38 | 39 | class Results { 40 | val property = "property" 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/info/D_HowToUseHotkeys.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.info 2 | 3 | object D_HowToUseHotkeys { 4 | 5 | /* 6 | * Intellij idea and Android studio have a lot of templates, shortcuts and hot keys. 7 | * And is very flexible and customizable. There are several of hot keys: 8 | * */ 9 | 10 | // For a fast jump to a method or variable, place a cursor on it and press "Ctrl+B". 11 | private fun jumpToMethod() { 12 | } 13 | 14 | // For a fast jump to the place where you just modified the code, 15 | // press "Ctrl+Shift+Backspace". 16 | // ---> Write something, place cursor to a different place, press combo. 17 | 18 | // To memorize several places you are working, place cursor to the line and press "Ctrl+Shift+[1..9]". 19 | // For a jump, press "Ctrl+[1..9]". To clear bookmarks press the same combo in the same line, 20 | // or use another one, or press combo twice in a row at any other place. 21 | 22 | // For a fast jump to a line press "Ctrl+G" (go to the line). Enter the number in the dialog box. 23 | 24 | // To see a description, which types of arguments you have to provide to a function, 25 | // or what type this function returns, place a cursor on it and press "Ctrl+Q". 26 | private fun seeTheArgTypes() { 27 | hiddenArgsContainer(1, "2", 3) 28 | } 29 | 30 | // One of the "auto-complete" combos is "Ctrl+Space" or "Alt+Enter". 31 | // Start typing a class name, method, or class property and hit combo to see a suggestion. 32 | // "Alt+Enter" is also uses to see a suggestions how to solve syntax errors. 33 | 34 | // To fast line copy, press "Ctrl+C" at any place of the line 35 | 36 | // To fast line copy and cut, press "Ctrl+X" at any place of the line 37 | 38 | // To duplicate a current line, 39 | // place a cursor to the line and press "Ctrl+D" 40 | 41 | // To insert a new line below the current line, 42 | // press "Shift+Enter" 43 | 44 | // To move a line upper or lower, 45 | // place cursor to the line, press "Alt+Shift" and move line with Up or Down arrows. 46 | 47 | @JvmStatic 48 | fun main(args: Array) { 49 | jumpToMethod() 50 | } 51 | 52 | /** 53 | * An example to demonstrate Ctrl+Q 54 | */ 55 | private fun hiddenArgsContainer(a: Int, b: String, c: Any): String { 56 | return "" 57 | } 58 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop1.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf", 7 | "RedundantNullableReturnType", 8 | "RedundantExplicitType", 9 | "unused" 10 | ) 11 | 12 | package day_1_kotlin.langeng.solutions 13 | 14 | import java.util.* 15 | 16 | // Workshop #1 - val, var, null, kotlin null safety, Elvis operator 17 | 18 | object KotlinWorkshop1 { 19 | 20 | @JvmStatic 21 | fun main(args: Array) { 22 | 23 | // Initializing variables. Pay attention - it's nullable! 24 | // Don't touch! Given: 25 | val nullableElvisString: String? = null 26 | val nullableAssertionString: String? = "potentially null" 27 | val emptyString = "" 28 | 29 | 30 | 31 | /* Exercise area */ 32 | 33 | // TODO 1: Uncomment. 34 | // Assign "nullableElvisString" to the "notNullUserString" and fix the assignment with elvis operator. 35 | // If "nullableElvisString" is null, "notNullUserString" should be equal to "emptyString". 36 | var notNullUserString: String = nullableElvisString ?: emptyString 37 | println("Result string is empty $notNullUserString") 38 | 39 | // TODO 2: Uncomment. 40 | // We know that "nullableString" is non-null by fact. Reassign value from "nullableAssertionString" using !! operator. 41 | notNullUserString = nullableAssertionString!! 42 | println("Result string is $notNullUserString") 43 | 44 | 45 | 46 | /* Exercise bonus area */ 47 | 48 | // TODO 3: Uncomment. Assign a sum of two numbers to "sum". 49 | // If first number is null, result should be null. If second one is null, result should be equal to first number. 50 | // Use '?' check, '.plus()' function and '?:' to add valid alternative inside '.plus()'. 51 | val notNullAlternative = 0 52 | val firstNumber: Int? = 10 53 | val secondNumber: Int? = 20 54 | val sum : Int? = firstNumber?.plus(secondNumber ?: notNullAlternative) 55 | println("Sum is {$sum}") 56 | 57 | 58 | // TODO 4: Uncomment. Store user String input in a "stringInput" variable. 59 | // While running the program. Look at the console. Click inside the console area. Input a string. 60 | print("Please, input a string: ") 61 | val stringInput: String? = MyScanner.scan.next() // <--- string input 1 62 | 63 | // TODO 5: Uncomment. 64 | // Store user Int input in "firstIntInput" and "secondIntInput" variables. 65 | // Replace the 'null' to calculate a "sumIntInputs". 66 | // Use '?' check, '.plus()' function and '?:' to add valid alternative inside '.plus()'. 67 | // While running the program. Look at the console. Click inside the console area. Input a string. 68 | print("Please, input a number: ") 69 | val firstIntInput: Int? = MyScanner.scan.nextInt() // <--- number input 1 70 | print("Please, input a second number: ") 71 | val secondIntInput: Int? = MyScanner.scan.nextInt() // <--- number input 2 72 | val sumIntInputs : Int? = firstIntInput?.plus(secondIntInput ?: notNullAlternative) // <--- replace 'null' with correct expression 73 | println("String:$stringInput, Summ of numbers:$sumIntInputs") 74 | 75 | 76 | 77 | /* Examples area */ 78 | 79 | val number: Int = -1 80 | val someNumber: Double = 2.5 81 | val someString: String = "Hello world" 82 | val someFlag: Boolean = true 83 | var someNullableNumber: Long? = null 84 | } 85 | } 86 | 87 | 88 | 89 | /* DO NOT TOUCH the utils below. */ 90 | 91 | class MyScanner { 92 | companion object { 93 | val scan = Scanner(System.`in`) 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop2.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | import java.util.* 4 | import kotlin.random.Random 5 | 6 | // Workshop #2 - control flow (if, when), arrays, for loop, if expression, return & jumps 7 | 8 | object KotlinWorkshop2 { 9 | 10 | // You may run the main function to test the code. 11 | @JvmStatic 12 | fun main(args: Array) { 13 | 14 | 15 | 16 | /* Exercise area */ 17 | 18 | // Initializing variables in runtime with input. 19 | // While running the program. Look at the console. Click inside the console window. Input a number. 20 | // Don't touch! Given: 21 | val upperBound = getUpperBound() 22 | val nonNullUpperBound = upperBound ?: 10 23 | val randomNumber = Random.nextInt(nonNullUpperBound) 24 | val scanner = Scanner(System.`in`) 25 | 26 | while (true) { 27 | // TODO 1: Add logic for comparing userInput with randomNumber with If-Else operator. 28 | // Break infinite while loop when user input correct number. Show message "Congratulations" 29 | // If user entered number below randomNumber - show message "Your Guess is Lower" 30 | // if user entered number over randomNumber - show message "Your Guess is Higher" 31 | 32 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 33 | // Storing user input in userInput variable 34 | // While running the program. Look at the console. Click inside the console window. Input a number. 35 | val userInput: Int = scanner.nextInt() 36 | if (userInput == randomNumber) { 37 | println("Congratulation, it was $randomNumber!") 38 | break 39 | 40 | } else if (userInput > randomNumber) { 41 | println("Your Guess is higher, continue.") 42 | 43 | } else { 44 | println("Your Guess is lower, continue.") 45 | } 46 | } 47 | 48 | 49 | 50 | /* Exercise bonus area */ 51 | 52 | // TODO 2: Uncomment. Initialize "numbersArray". 53 | // It should be an array of Int with capacity = 5. 54 | val numbersArray = intArrayOf(0, 0, 0, 0, 0) 55 | println("\nGiven numbersArray:") 56 | for ((index, number) in numbersArray.withIndex()){ 57 | println("$index $number") 58 | } 59 | 60 | // TODO 3: Uncomment. Initialize "size". 61 | // Change infinite while-loop condition. Limit user input with a size of "numbersArray". 62 | println("\nTraining 2. \"Fill in the collection\"") 63 | val size = numbersArray.size 64 | var counter = 0 65 | while (counter < size) { 66 | print("Input a number in range 0..10 inclusive: ") 67 | val userInput: Int = scanner.nextInt() 68 | 69 | // TODO 4: Add inputs to the "numbersArray" using the following logic: 70 | // if userInput is 3 - add this 3 number "as is". 71 | // if userInput is 5 - add 5 * size of numbersArray. 72 | // if userInput is 9 - add 2 + size of numbersArray. 73 | // else don't add anything. 74 | // Use "When" operator. 75 | when (userInput) { 76 | 3 -> numbersArray.set(counter, userInput) 77 | 5 -> numbersArray.set(counter, userInput * size) 78 | 9 -> numbersArray.set(counter, 2 + size) 79 | else -> { /* ignored */ } 80 | } 81 | 82 | counter++ 83 | } 84 | 85 | // TODO 5: Print line by line elements of numbersArray with their indexes. 86 | // Should looks like "index value". 87 | for ((index, number) in numbersArray.withIndex()){ 88 | println("$index $number") 89 | } 90 | } 91 | 92 | 93 | 94 | /* DO NOT TOUCH the utils below. */ 95 | 96 | private fun getUpperBound(): Int? { 97 | println("Training 1. \"Guess a number\"") 98 | print("Enter maximum number in range 10..20 inclusive: ") 99 | val scanner = Scanner(System.`in`) 100 | return try { 101 | scanner.nextInt() 102 | 103 | } catch (e: InputMismatchException) { 104 | null 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop3.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | import java.util.* 4 | import java.util.logging.Logger 5 | import kotlin.random.Random 6 | 7 | // Workshop #3 - functions, lambda, high-order function 8 | 9 | object KotlinWorkshop3 { 10 | 11 | // You can run the main function to test the code 12 | @JvmStatic 13 | fun main(args: Array) { 14 | // Initializing variables in runtime with input. 15 | // While running the program. Look at the console. Click inside the console window. Input a number. 16 | // Don't touch! Given: 17 | val scanner = Scanner(System.`in`) 18 | val upperBound = getUpperBound(scanner) 19 | val nonNullUpperBound = upperBound ?: 10 20 | val randomNumber = Random.nextInt(nonNullUpperBound) 21 | val capacity = nonNullUpperBound 22 | val guesses = createIntArrayOfCapacity(capacity) 23 | 24 | 25 | 26 | /* Exercise area */ 27 | 28 | var guessed = false 29 | var counter = 0 30 | while (!guessed && counter < capacity) { 31 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 32 | // Storing user input in userInput variable 33 | // While running the program. Look at the console. Click inside the console window. Input a number. 34 | val userInput: Int = getNextInput(scanner, nonNullUpperBound) 35 | guesses[counter] = userInput 36 | 37 | // TODO 1: Uncomment. Declare playRound function: takes 2 integer arguments and returns a boolean. 38 | guessed = playRound(userInput, randomNumber) 39 | 40 | counter++ 41 | } 42 | 43 | // TODO (bonus): Create analytics system for the game. Collect stats and print. 44 | printGameStats(guesses, counter, randomNumber) 45 | } 46 | 47 | // TODO 1: Uncomment. Declare playRound function: takes 2 integer arguments and returns a boolean. 48 | // TODO 2: Add logic for comparing userInput with randomNumber with If-Else operator. 49 | // Break infinite while loop when user input correct number. Show message "Congratulations" 50 | // If user entered number below randomNumber - show message "Your Guess is Lower" 51 | // if user entered number over randomNumber - show message "Your Guess is Higher". 52 | // See workshop #2 53 | private fun playRound(userInput: Int, randomNumber: Int): Boolean { 54 | when { 55 | userInput == randomNumber -> { 56 | println("Congratulation, it was $randomNumber!") 57 | return true 58 | } 59 | userInput > randomNumber -> { 60 | println("Your Guess is higher, continue.") 61 | } 62 | else -> { 63 | println("Your Guess is lower, continue.") 64 | } 65 | } 66 | 67 | return false 68 | } 69 | 70 | 71 | 72 | /* Exercise bonus area */ 73 | 74 | // TODO (bonus): Create analytics system for the game. Collect stats and print. 75 | private fun printGameStats(guesses: IntArray, guessCounter: Int, randomNumber: Int) { 76 | // TODO 3: Uncomment. Print total guesses count. 77 | printTotalCountOfGuesses(guessCounter) 78 | 79 | // TODO 4: Uncomment. 80 | // Add high level function "countHigherGuesses" for printing higher elements from array. 81 | countHigherGuesses(guesses, randomNumber) { counter -> 82 | println("Total count of higher guesses: $counter\n") 83 | } 84 | 85 | // TODO 5: Uncomment. 86 | // Create lambda function "countLowerGuesses" for printing lower elements from array. 87 | // Do not print element if its value == "-1", the default value given to array on a initializing stage. 88 | countLowerGuesses(guesses, randomNumber) 89 | 90 | // TODO 6: Uncomment. 91 | // Print every element of guesses in separate line via .forEach high-level function. 92 | println("All guesses:") 93 | guesses.forEach { 94 | print("$it, ") 95 | } 96 | } 97 | 98 | // TODO 3 99 | // Should print total guesses count. 100 | private fun printTotalCountOfGuesses(guessCounter: Int) { 101 | println("\nTotal count: $guessCounter\n") 102 | } 103 | 104 | // TODO 4 105 | // Should count and print guesses that were higher than randomNumber. 106 | // Should return count as fun result. 107 | private fun countHigherGuesses( 108 | guesses: IntArray, 109 | randomNumber: Int, 110 | printer: (Int) -> Unit 111 | ): Int { 112 | 113 | var counter = 0 114 | for (guess in guesses) { 115 | if (guess > randomNumber) { 116 | counter++ 117 | println("$counter) $guess is higher than $randomNumber") 118 | } 119 | } 120 | 121 | printer(counter) 122 | 123 | return counter 124 | } 125 | 126 | // TODO 5 127 | // Should count and print guesses that were lower than randomNumber. 128 | val countLowerGuesses: (IntArray, Int) -> Unit = { guesses, randomNumber -> 129 | var counter = 0 130 | for (guess in guesses) { 131 | if (guess != -1 && guess < randomNumber) { 132 | counter++ 133 | println("$counter) $guess is lower than $randomNumber") 134 | } 135 | } 136 | 137 | println("Total count of lower guesses: $counter\n") 138 | } 139 | 140 | 141 | 142 | /* DO NOT TOUCH the utils below. */ 143 | 144 | private fun getUpperBound(scanner: Scanner): Int? { 145 | val upperLimit = 20 146 | val lowerLimit = 1 147 | 148 | println("Game: \"Guess a number\"") 149 | print("Enter maximum number in range 1..20 inclusive: ") 150 | return try { 151 | var input = scanner.nextInt() 152 | if (input in lowerLimit..upperLimit) { 153 | input 154 | 155 | } else { 156 | println("Wrong number. Use default as limit: $upperLimit") 157 | upperLimit 158 | } 159 | 160 | } catch (e: InputMismatchException) { 161 | null 162 | } 163 | } 164 | 165 | private fun getNextInput(scanner: Scanner, nonNullUpperBound: Int): Int { 166 | val lowerLimit = 0 167 | val badResult = -1 168 | 169 | return try { 170 | var input = scanner.nextInt() 171 | if (input in lowerLimit..nonNullUpperBound) { 172 | input 173 | 174 | } else { 175 | println("Wrong input. Should be $nonNullUpperBound or lower.") 176 | badResult 177 | } 178 | 179 | } catch (e: InputMismatchException) { 180 | val log = Logger.getLogger("KotlinWorkshop3Logger") 181 | log.throwing("KotlinWorkshop3Logger", "getNextInput()", e) 182 | badResult 183 | } 184 | } 185 | 186 | private fun createIntArrayOfCapacity(capacity: Int): IntArray { 187 | return IntArray(capacity) { i -> -1 } 188 | } 189 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop4.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // Workshop #4 - classes 4 | 5 | object KotlinWorkshop4 { 6 | 7 | // Don't touch! Given: 8 | @JvmStatic 9 | fun main(args: Array) { 10 | testBus() 11 | } 12 | 13 | 14 | 15 | /* Exercise area */ 16 | 17 | // TODO 1: Declare a class Bus that will have integer amount of "passengersCount" as a property. 18 | // ? Classes should be declared in the bottom of a file. Below functions. 19 | // There is an exception. We sort declarations by TODOs. 20 | class Bus(private val passengersCount: Int) { 21 | 22 | // TODO 2: Add method "drive" without arguments that will print "Driving n passengers to the destination" 23 | // where n - count of passengers. 24 | fun drive() { 25 | println("Driving $passengersCount passengers to the destination") 26 | } 27 | } 28 | 29 | private fun testBus() { 30 | // TODO 3: Create an instance of your class. 31 | val bus = Bus(10) 32 | 33 | // TODO 4: Drive your bus to the destination and check out that the output is correct. 34 | bus.drive() 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop5.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // Workshop #5 - inheritance, abstract, interface 4 | 5 | // Don't touch! Given: 6 | // Declare a contract for a transport ability. 7 | interface Driveable { 8 | fun drive() 9 | } 10 | 11 | // Declare a transport class which describes passenger transport of all types. 12 | // Give this transport an ability to drive. 13 | abstract class Transport(protected var passengersCount: Int): Driveable 14 | 15 | // Create a Bicycle transport which can carry a single person. 16 | class Bicycle: Transport(1) { 17 | override fun drive() { 18 | println("Ride a bicycle.") 19 | } 20 | } 21 | 22 | 23 | 24 | /* Exercise area */ 25 | 26 | // TODO 1: Create a new interface that will be appropriate for new classes below. 27 | // ? By convention, names of Classes and Interfaces start with an upper case letter and use the camel case. 28 | // Example: "SomeLongClassName". 29 | interface Fuelable { 30 | fun isFull(): Boolean 31 | fun fuel() 32 | } 33 | 34 | // TODO 2: Write your own class Bus and some Car. 35 | // Instead of writing it from scratch, extend it from the Transport class and your new interface. 36 | // ? Class can extends only one other class, but implements many interfaces, i.e.: 37 | // class Kitty(): Cat, Cuteable, Sleepable, Furryable {} 38 | class Bus(passengersCount: Int): Transport(passengersCount), Fuelable { 39 | 40 | private var hasFuel = false 41 | 42 | override fun drive() { 43 | if (isFull()) { 44 | hasFuel = false 45 | println("Driving $passengersCount passengers to the destination") 46 | 47 | } else { 48 | println("Don't have fuel. Hey passengers, let's push this thing together!") 49 | } 50 | } 51 | 52 | override fun isFull(): Boolean = hasFuel 53 | 54 | override fun fuel() { 55 | hasFuel = true 56 | println("Fueled a bit!") 57 | } 58 | } 59 | 60 | // TODO 2: Write your own class Bus and some Car. 61 | // Instead of writing it from scratch, extend it from the Transport class and your new interface. 62 | class Car(passengersCount: Int): Transport(passengersCount), Fuelable { 63 | 64 | private var hasFuel = false 65 | 66 | override fun drive() { 67 | if (isFull()) { 68 | println("Driving a car with a speed of light! $passengersCount passengers on board.") 69 | hasFuel = false 70 | 71 | } else { 72 | println("Don't have fuel.") 73 | } 74 | } 75 | 76 | override fun isFull(): Boolean = hasFuel 77 | 78 | override fun fuel() { 79 | hasFuel = true 80 | println("Filled up with gasoline!") 81 | } 82 | } 83 | 84 | // TODO 3: Test your transport in appropriate sections 85 | object VehiclesTest { 86 | 87 | // You can run the main function to test the code 88 | @JvmStatic 89 | fun main(args: Array) { 90 | testBus() 91 | testCar() 92 | testBicycle() 93 | 94 | testBusParts() 95 | } 96 | 97 | private fun testBus() { 98 | println("\nTesting how bus drives...") 99 | val bus = Bus(10) 100 | bus.drive() 101 | bus.fuel() 102 | bus.drive() 103 | } 104 | 105 | private fun testCar() { 106 | println("\nTesting how car drives...") 107 | val car = Car(4) 108 | car.drive() 109 | car.fuel() 110 | car.drive() 111 | } 112 | 113 | private fun testBicycle() { 114 | println("\nTesting how bicycle drives...") 115 | val bicycle = Bicycle() 116 | bicycle.drive() 117 | } 118 | 119 | 120 | 121 | /* Exercise bonus area */ 122 | 123 | // TODO 4: Test bus abilities as separate features. 124 | private fun testBusParts() { 125 | val bus = Bus(0) 126 | 127 | val engine: Driveable = bus 128 | println("\nTesting bus's engine:") 129 | println(engine.drive()) 130 | 131 | val pump: Fuelable = bus 132 | println("\nTesting bus's fuel system:") 133 | println("has fuel: ${pump.isFull()}") 134 | println(pump.fuel()) 135 | println("has fuel: ${pump.isFull()}") 136 | } 137 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop6.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // Workshop #6 - special classes, objects, data classes 4 | 5 | 6 | 7 | /* Exercise area */ 8 | 9 | // TODO 1: Add 2-4 properties to the data class. 10 | data class VideoGame( 11 | val name: String, 12 | val year: Int, 13 | val genre: Genre /* ignored till TODO 6 */, 14 | val rate: Int = 5 /* ignored till TODO 7 */ 15 | ) 16 | 17 | // TODO 2: Create on object that will be used to test the games, call it "VideoGamesTest". 18 | object VideoGameTest { 19 | 20 | @JvmStatic 21 | fun main(args: Array) { 22 | // TODO 3: Create an instance of VideoGame. 23 | // Make a copy via .copy() method and store the copy to another variable. 24 | val game = VideoGame("Heroes of Might and Magic III", 1999, Genre.STRATEGY) 25 | val copy = game.copy() 26 | 27 | // TODO 4: Print out if those data class objects are equal. 28 | // Use "==" to compare. Should be true. 29 | val equal = game == copy 30 | println("Objects are equal $equal") 31 | 32 | // TODO 5: Put several data class objects into an array and print them out. 33 | val games = arrayOf(game, game.copy(name = "Heroes 4", year = 2002), VideoGame("NFS", 2000, Genre.RACING)) 34 | games.forEach { 35 | println(it) 36 | } 37 | 38 | 39 | 40 | /* Examples area */ 41 | 42 | // TODO 6, TODO 7 43 | val dn3d = VideoGame( 44 | name = "Duke Nukem 3D", 45 | year = 1996, 46 | genre = Genre.ACTION 47 | ) 48 | println("\n" + dn3d) 49 | } 50 | } 51 | 52 | 53 | 54 | /* Exercise bonus area */ 55 | 56 | // TODO 6: Create an enum class Genre with a few values, and add it as a field to the VideoGame. 57 | // Fix created video game instances in the main() function. 58 | enum class Genre { 59 | STRATEGY, 60 | RACING, 61 | ACTION 62 | } 63 | 64 | // TODO 7: Add a new property to the VideoGame class with default value. 65 | // As you can see, you don't have to fix already created instances. 66 | // But you have to remember that this can change a behaviour of instances in some cases. 67 | // Run program and see new print results. -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop7.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // Workshop #7 - list, mutable list, useful functions, maps 4 | 5 | object KotlinWorkshop7 { 6 | 7 | @JvmStatic 8 | fun main(args: Array) { 9 | 10 | // Don't touch! Given: 11 | val sadPoem = arrayOf( 12 | "True happiness can be attained", 13 | "Only if one's surroundings are good.", 14 | "It's not true that good exists", 15 | "I'm sure you can agree that", 16 | "The reality", 17 | "Creates", 18 | "My attitude", 19 | "It's all beyond my control", 20 | "And you'll never in a million years hear me say that", 21 | "Today was a very good day." 22 | ) 23 | 24 | 25 | 26 | /* Exercise area */ 27 | 28 | // TODO 1: Print the "poem" for 2 cases: 29 | // 1. Filter and print lines shorter than 12 symbols; 30 | // 2. Print poem reversed. 31 | val filtered = sadPoem.filter { it.length < 12 } 32 | val reversed = sadPoem.reversed() 33 | println("\nFiltered: $filtered") 34 | println("\nReversed: $reversed") 35 | println("\n") 36 | 37 | // TODO 2: Uncomment. 38 | // Initialize an evenList variable and add to it only "even" numbers from 0 to 50. 39 | val evenList = mutableListOf() 40 | for (i in 0..50 step 2) { 41 | evenList.add(i) 42 | } 43 | println("\nEven numbers: $evenList") 44 | 45 | 46 | // Don't touch! Given: 47 | val weatherMap = mutableMapOf( 48 | "Moscow" to 2, 49 | "St. Petersburg" to -1, 50 | "Minsk" to 4 51 | ) 52 | 53 | 54 | 55 | /* Exercise bonus area */ 56 | 57 | // TODO 3. Add a weather for Kiev and Tel-Aviv to weatherMap. 58 | weatherMap["Kiev"] = 6 59 | weatherMap["Tel-Aviv"] = 20 60 | 61 | // TODO 4. Filter and print cities with temperature of zero+. 62 | // Connect operators as a chain. 63 | weatherMap.filter { 64 | it.value > 0 65 | }.forEach { 66 | println("City ${it.key} has temperature of ${it.value}") 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop8.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // workshop #8 - const, companion object, extension func 4 | 5 | 6 | fun main(){ 7 | val list = mutableListOf("1", 3, 4, "Patrick", 3.4, "123-59") 8 | 9 | val p = Person("45-45-45") 10 | 11 | println("list:$list, code:${p.code}") 12 | val changedList = list.replacePlacesWithThePhoneCode(p, 4) 13 | println("changedList:$changedList") 14 | } 15 | 16 | 17 | class Person(phoneCode: String) { 18 | val code = if (phoneCode.length > maxLengthDone) phoneCode.subSequence(0, maxLengthDone) else phoneCode 19 | 20 | companion object { 21 | private const val maxLengthDone = 12 22 | } 23 | } 24 | 25 | fun List.replacePlacesWithThePhoneCode(person: Person, placeNum: Int = 3): List { 26 | return this.mapIndexed { index, any -> if (index % placeNum == 0) person.code else any} 27 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langeng/solutions/KotlinWorkshop9.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langeng.solutions 2 | 3 | // workshop #9 - generics 4 | 5 | fun main() { 6 | val p = ProgrammerDone() 7 | 8 | p.learn(Kotlin("basics")) 9 | 10 | p.learn(Kotlin("generics")) 11 | p.learn(Kotlin("coroutines")) 12 | 13 | // should be equal to 3 14 | println(p.howManyConceptsDoIKnow()) 15 | 16 | //should be Kotlin(element=coroutines) 17 | println(p.lastConcept()) 18 | 19 | p.forget(Kotlin("generics")) 20 | // should be equal to 3 21 | println(p.howManyConceptsDoIKnow()) 22 | } 23 | 24 | 25 | interface Language{ 26 | val element: String 27 | } 28 | 29 | data class JavaLanguage(override val element: String) : Language 30 | data class Kotlin(override val element: String): Language 31 | data class Swift(override val element: String): Language 32 | data class C_Sharp(override val element: String): Language 33 | 34 | 35 | class ProgrammerDone() { 36 | 37 | private val concepts = mutableListOf() 38 | 39 | fun howManyConceptsDoIKnow(): Int = concepts.size 40 | 41 | fun learn(concept: T) { 42 | concepts.add(concept) 43 | } 44 | 45 | fun forget(concept: T) { 46 | concepts.remove(concept) 47 | } 48 | 49 | fun lastConcept(): T = concepts.last() 50 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop1.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf", 7 | "RedundantNullableReturnType", 8 | "RedundantExplicitType", 9 | "unused" 10 | ) 11 | 12 | package day_1_kotlin.langrus.assignments 13 | 14 | import java.util.* 15 | 16 | // Практическая работа #1 - val, var, null, kotlin null безопасность, Элвис оператор 17 | 18 | object KotlinWorkshop1 { 19 | 20 | @JvmStatic 21 | fun main(args: Array) { 22 | 23 | // Инициализация переменных. Обрати внимание, они могут принимать значение null. 24 | // Не исправляй! Дано: 25 | val nullableElvisString: String? = null 26 | val nullableAssertionString: String? = "потенциально null" 27 | val emptyString = "" 28 | 29 | 30 | /* Рабочая зона */ 31 | 32 | // TODO 1: Раскомментируй. 33 | // Присвой "notNullUserString" значение из "nullableElvisString". 34 | // Если "nullableElvisString" равно null, сделай значение "notNullUserString" равным значению пустой строки "emptyString". 35 | // Исправить присвоение используя Элвис-оператор "?:". 36 | // var notNullUserString: String = 37 | // println("Строка результат равна $notNullUserString") 38 | 39 | // TODO 2: Раскомментируй. 40 | // По факту мы знаем, что значение "nullableAssertionString" не равно null. 41 | // Сделай принудительное присвоение используя !! оператор. 42 | // notNullUserString = 43 | // println("Строка результат равна $notNullUserString") 44 | 45 | 46 | /* Бонусные задания */ 47 | 48 | // TODO 3: Раскомментируй. Сложи две переменные. 49 | // Если firstNumber равно null, сумма должна быть null. Если secondNumber равно null, сумма должна быть равна значение firstNumber. 50 | // Используй проверку на null '?', для сложения используй функцию '.plus()'. Внутри '.plus()' используй '?:'. 51 | val notNullAlternative = 0 52 | val firstNumber: Int? = 10 53 | val secondNumber: Int? = 20 54 | // val sum : Int? = 55 | // println("Сумма равна {$sum}") 56 | 57 | 58 | // TODO 4: Раскомментируй. Сохрани строку введённую с клавиатуры в переменную "stringInput". 59 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 60 | // Кликни в зоне открытого окна и введи строку. 61 | // print("Пожалуйста введите строку: ") 62 | // val stringInput: String? = MyScanner.scan.next() // <--- string input 1 63 | 64 | // TODO 5: Раскомментируй. 65 | // Сохрани значения чисел введённух с клавиатуры в переменные "firstIntInput" и "secondIntInput". 66 | // Сохраните сумму введенных чисел в "sumIntInputs". Вместо потенциального 'null' подставьте значение по умолчанию. 67 | // Используй проверку на null '?', для сложения используй функцию '.plus()'. Внутри '.plus()' используй '?:'. 68 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 69 | // Кликни в зоне открытого окна и введи строку. 70 | // print("Пожалуйста введите первое число: ") 71 | // val firstIntInput: Int? = MyScanner.scan.nextInt() // <--- вводим первое число 72 | // print("Пожалуйста введите второе число: ") 73 | // val secondIntInput: Int? = MyScanner.scan.nextInt() // <--- вводим второе число 74 | // val sumIntInputs : Int? = firstIntInput?.plus(secondIntInput ?: null) // <--- делаем замену потенциального 'null' значением по умолчанию 75 | // println("Исходная строка: $stringInput, Сумма чисел: $sumIntInputs") 76 | 77 | 78 | /* Примеры */ 79 | 80 | val number: Int = -1 81 | val someNumber: Double = 2.5 82 | val someString: String = "Привет, мир!" 83 | val someFlag: Boolean = true 84 | var someNullableNumber: Long? = null 85 | } 86 | } 87 | 88 | 89 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 90 | 91 | class MyScanner { 92 | companion object { 93 | val scan = Scanner(System.`in`) 94 | } 95 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop2.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf" 7 | ) 8 | 9 | package day_1_kotlin.langrus.assignments 10 | 11 | import java.util.* 12 | import kotlin.random.Random 13 | 14 | // Практическая работа #2 - control flow (if, when), arrays, for loop, if expression, return & jumps 15 | 16 | object KotlinWorkshop2 { 17 | 18 | // Запусти исполнение main() функции, для выполнения кода. 19 | // См. подробнее в /../info/B_HowToRunProgram 20 | @JvmStatic 21 | fun main(args: Array) { 22 | 23 | 24 | /* Рабочая зона */ 25 | 26 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 27 | // Кликни в зоне открытого окна и введи строку. 28 | // Не исправляй! Дано: 29 | val upperBound = getUpperBound() 30 | val nonNullUpperBound = upperBound ?: 10 31 | val randomNumber = Random.nextInt(nonNullUpperBound) 32 | val scanner = Scanner(System.`in`) 33 | 34 | while (true) { 35 | // TODO 1: Напиши логику сравнения "userInput" с "randomNumber" используя If-Else выражение. 36 | // Когда ввод с клавиатуры равен значению "randomNumber", прерви бесконечный цикл while 37 | // используя ключевое слово "break" и выведи сообщение "Поздравляю! Задуманное число х" 38 | // Если введено число меньше "randomNumber", выведи сообщение "Ваше число меньше задуманного, пожалуйста продолжаем." 39 | // Если введено число больше "randomNumber", выведи сообщение "Ваше число больше задуманного, пожалуйста продолжаем." 40 | 41 | print("Введите число в диапазоне 0..$nonNullUpperBound включительно: ") 42 | // Сохраняем введённое с клавиатуры число в "userInput". 43 | val userInput: Int = scanner.nextInt() 44 | if (true) { 45 | 46 | } 47 | } 48 | 49 | 50 | /* Бонусные задания */ 51 | 52 | // TODO 2: Раскомментируй. Проинициализируй "numbersArray". 53 | // "numbersArray" это массив целочисленных значений, длинной 5 чисел. 54 | // val numbersArray = 55 | 56 | // TODO 3: Раскомментируй. Проинициализируй свойство "size" длинной массива "numbersArray". 57 | // Измени условия повтора бесконечного цикла while так, чтобы он стал конечным и выполнился не более "size" раз. 58 | println("\n Программа 2. \"Введите коллекцию чисел\"") 59 | // val size = 60 | var counter = 0 61 | while (true) { 62 | print("Введите число в диапазоне 0..10 включительно: ") 63 | val userInput: Int = scanner.nextInt() 64 | 65 | // TODO 4: Сохрани и добавь введённые с клавиатуры числа в массив "numbersArray" согласно следующей логики: 66 | // - Если введено 3 - добавь число в массив без изменений; 67 | // - Если введено 5 - умнож и добавь (5 * size); 68 | // - Если введено 9 - сложи и добавь (2 + size); 69 | // - Иначе не добавляй ничего. 70 | // Используй выражение "When". 71 | when { 72 | 73 | } 74 | 75 | counter++ 76 | } 77 | 78 | // TODO 5: Выведи в консоль значения элементов массива и индекс, на котором они находятся. 79 | // Новый элемент на новой строке. Это должно выглядеть как "индекс: значение". 80 | 81 | } 82 | 83 | 84 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 85 | 86 | private fun getUpperBound(): Int? { 87 | println("Программа 1. \"Угадай число\"") 88 | print("Введите число максимум в диапазоне 10..20 включительно: ") 89 | val scanner = Scanner(System.`in`) 90 | return try { 91 | scanner.nextInt() 92 | 93 | } catch (e: InputMismatchException) { 94 | null 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop3.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("CanBeVal", "UNUSED_PARAMETER", "unused", "UNUSED_VARIABLE", "UNUSED_ANONYMOUS_PARAMETER") 2 | 3 | package day_1_kotlin.langrus.assignments 4 | 5 | import java.util.* 6 | import java.util.logging.Logger 7 | import kotlin.random.Random 8 | 9 | // Workshop #3 - functions, lambda, high-order function 10 | 11 | object KotlinWorkshop3 { 12 | 13 | // Запусти исполнение main() функции, для выполнения кода. 14 | // См. подробнее в /../info/B_HowToRunProgram 15 | @JvmStatic 16 | fun main(args: Array) { 17 | 18 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 19 | // Не исправляй! Дано: 20 | val scanner = Scanner(System.`in`) 21 | val upperBound = getUpperBound(scanner) 22 | val nonNullUpperBound = upperBound ?: 10 23 | val randomNumber = Random.nextInt(nonNullUpperBound) 24 | val capacity = nonNullUpperBound 25 | val guesses = createIntArrayOfCapacity(capacity) 26 | 27 | 28 | 29 | /* Рабочая зона */ 30 | 31 | var guessed = false 32 | var counter = 0 33 | while (!guessed && counter < capacity) { 34 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 35 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 36 | val userInput: Int = getNextInput(scanner, nonNullUpperBound) 37 | guesses[counter] = userInput 38 | 39 | // TODO 1: Раскомментируй. 40 | // Объяви функцию "playRound": она должна принимать на вход два Int аргумента и возвращать Boolean. 41 | // См. ниже. 42 | // guessed = playRound(userInput, randomNumber) 43 | 44 | counter++ 45 | } 46 | 47 | // TODO (bonus): Напиши аналитическцую систему для игрового раунда, 48 | // которая будет собирать статистику и печатать результат. См. ниже. 49 | printGameStats(guesses, counter, randomNumber) 50 | } 51 | 52 | // TODO 1: Раскомментируй. 53 | // Объяви функцию "playRound": она должна принимать на вход два Int аргумента и возвращать Boolean. 54 | // TODO 2: Функция возвращает "true" и выводит сообщение "Congratulations!", 55 | // когда ввод с клавиатуры равен значению "randomNumber"; 56 | // Если введено число больше "randomNumber", выведи сообщение "Your Guess is higher, continue." и верни false; 57 | // Если введено число меньше "randomNumber", выведи сообщение "Your Guess is lower, continue." и верни false. 58 | // Можно использовать наработки из workshop 2, с отличием, что здесь это вынесенная функция, нет цикла и возвращает результат. 59 | // private fun playRound(...) : ... { 60 | // 61 | // return false 62 | // } 63 | 64 | 65 | 66 | /* Бонусные задания */ 67 | 68 | // TODO (bonus): Напиши аналитическцую систему для игрового раунда, 69 | // которая будет собирать статистику и печатать результат. См. ниже. 70 | private fun printGameStats(guesses: IntArray, guessCounter: Int, randomNumber: Int) { 71 | // TODO 3: Раскомментируй. Выведи общее число попыток ввода. 72 | // printTotalCountOfGuesses(guessCounter) 73 | 74 | // TODO 4: Раскомментируй. 75 | // Напиши функцию высшего порядка "countHigherGuesses" для вывода всех попыток воода, которые оказались выше "randomNumber". 76 | // Функция должна возвращать число таких попыток как результат. 77 | // countHigherGuesses(guesses, randomNumber) { counter -> 78 | // println("Total count of higher guesses: $counter\n") 79 | // } 80 | 81 | // TODO 5: Раскомментируй. 82 | // Напиши lambda-выражение "countLowerGuesses" для вывода всех попыток воода, которые оказались ниже "randomNumber". 83 | // И не равны значению "-1", заданному элементу массива при инициализации массива. 84 | // countLowerGuesses(guesses, randomNumber) 85 | 86 | // TODO 6: Раскомментируй. 87 | // Выведи результаты всех попыток ввода, строка за строкой. 88 | // Используй функцию высшего порядка ".forEach". 89 | // guesses 90 | } 91 | 92 | // TODO 3 93 | private fun printTotalCountOfGuesses(guessCounter: Int) { 94 | TODO() 95 | } 96 | 97 | // TODO 4 98 | private fun countHigherGuesses( 99 | guesses: IntArray, 100 | randomNumber: Int, 101 | printer: (Int) -> Unit 102 | 103 | ): Int { 104 | var counter = 0 105 | TODO() 106 | } 107 | 108 | // TODO 5 109 | val countLowerGuesses: (IntArray, Int) -> Unit = { guesses, randomNumber -> 110 | TODO() 111 | } 112 | 113 | 114 | 115 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 116 | 117 | private fun getUpperBound(scanner: Scanner): Int? { 118 | val upperLimit = 20 119 | val lowerLimit = 1 120 | 121 | println("Game: \"Guess a number\"") 122 | print("Enter maximum number in range 1..20 inclusive: ") 123 | return try { 124 | var input = scanner.nextInt() 125 | if (input in lowerLimit..upperLimit) { 126 | input 127 | 128 | } else { 129 | println("Wrong number. Use default as limit: $upperLimit") 130 | upperLimit 131 | } 132 | 133 | } catch (e: InputMismatchException) { 134 | null 135 | } 136 | } 137 | 138 | private fun getNextInput(scanner: Scanner, nonNullUpperBound: Int): Int { 139 | val lowerLimit = 0 140 | val badResult = -1 141 | 142 | return try { 143 | var input = scanner.nextInt() 144 | if (input in lowerLimit..nonNullUpperBound) { 145 | input 146 | 147 | } else { 148 | println("Wrong input. Should be $nonNullUpperBound or lower.") 149 | badResult 150 | } 151 | 152 | } catch (e: InputMismatchException) { 153 | val log = Logger.getLogger("KotlinWorkshop3Logger") 154 | log.throwing("KotlinWorkshop3Logger", "getNextInput()", e) 155 | badResult 156 | } 157 | } 158 | 159 | private fun createIntArrayOfCapacity(capacity: Int): IntArray { 160 | return IntArray(capacity) { i -> -1 } 161 | } 162 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop4.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.assignments 2 | 3 | // Workshop #4 - classes 4 | 5 | object KotlinWorkshop4 { 6 | 7 | // Не исправляй! Дано: 8 | @JvmStatic 9 | fun main(args: Array) { 10 | testBus() 11 | } 12 | 13 | 14 | 15 | /* Рабочая зона */ 16 | 17 | // TODO 1: Объяви класс "Bus" который в качестве аргумента будет получать число "passengersCount". 18 | // ? Хорошим тоном считается объявлять классы и интерфейсы внизу файла, под функциями. 19 | // Здесь, и в других частях практической работы, классы и функции отсортированы по порядку выполнения заданий. 20 | // class ...(...) { 21 | 22 | // TODO 2: Добавь функцию "drive", без аргументов. 23 | // Она должна выводить фразу "Driving N passengers to the destination", где N - число пассажиров. 24 | 25 | // fun drive() { 26 | // println("Drive on car") 27 | // } 28 | // } 29 | 30 | private fun testBus() { 31 | // TODO 3: Создайте экземпляр класса "Bus". 32 | // val bus = ... 33 | 34 | // TODO 4: Отправь автобус к пункту назначения и проверь, что выведется в консоль. 35 | // ... .drive() 36 | } 37 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop5.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package day_1_kotlin.langrus.assignments 4 | 5 | // Workshop #5 - inheritance, abstract, interface 6 | 7 | // Не исправляй! Дано: 8 | // Объявляем контракт, представляющий некое свойство транспорта. 9 | interface Driveable { 10 | fun drive() 11 | } 12 | 13 | // Объявляем класс пассажирского транспорта вцелом. 14 | // Придадим такому транспорту свойство перемещаться под управлением водителя. 15 | abstract class Transport(protected var passengersCount: Int): Driveable 16 | 17 | // Создадим реальный транспорт: "Велосипед". Он может управляться водителем и перевозит одного пассажира. 18 | class Bicycle: Transport(1) { 19 | override fun drive() { 20 | println("Ride a bicycle.") 21 | } 22 | } 23 | 24 | 25 | 26 | /* Рабочая зона */ 27 | 28 | // TODO 1: Создай свой интерфейс - контракт, который бы также подошел по смыслу классу транспорт. 29 | // См. ниже. 30 | // ? Имена классов и файлов Котлин принято называть с заглавной буквы, в формате "camelCase". 31 | // Например: "SomeLongClassName" 32 | //interface ... 33 | 34 | // TODO 2: Создай свои собственные классы, например "Bus" и "Car". 35 | // Эти классы не будут полностью написаны с нуля, они должны расширять общий класс "Transport", 36 | // и дополнительно реализовывать придуманный тобой интерфейс. 37 | // ? Класс может наследовать только один класс, но реализовывать несколько интерфейсов, например: 38 | // class Kitty(): Cat, Cuteable, Sleepable, Furryable {} 39 | //class Bus ... 40 | //class Car ... 41 | 42 | // TODO 3: Протестируй работоспособность твоего транспорта. 43 | object VehiclesTest { 44 | 45 | // Запусти исполнение main() функции, для выполнения кода. 46 | @JvmStatic 47 | fun main(args: Array) { 48 | testBus() 49 | testCar() 50 | testBicycle() 51 | } 52 | 53 | private fun testBus() { 54 | println("Testing how bus drives...") 55 | // val bus = ... 56 | } 57 | 58 | private fun testCar() { 59 | println("Testing how car drives...") 60 | // val car = ... 61 | } 62 | 63 | private fun testBicycle() { 64 | println("Testing how bicycle drives...") 65 | // ... 66 | } 67 | 68 | 69 | 70 | /* Бонусные задания */ 71 | 72 | // TODO 4: Протестируй агрегаты автобуса, как независимые компоненты. 73 | // Т.е. каждый набор независимых свойств - отдельно, чтобы в тестируемой сущности были скрыты все свойства, 74 | // не принадлежащие к данному набору. 75 | private fun testBusParts() { 76 | println("Testing bus's feature 1...") 77 | 78 | 79 | println("Testing bus's feature 2...") 80 | 81 | } 82 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop6.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.assignments 2 | 3 | // Workshop #6 - special classes, objects, data classes 4 | 5 | 6 | 7 | /* Рабочая зона */ 8 | 9 | // TODO 1: Добавь в data class 2-4 свойства. 10 | // data class VideoGame(...) 11 | 12 | // TODO 2: Создай объект "VideoGamesTest", который будет использоваться для тестирования игр. 13 | // ... VideoGamesTest { 14 | 15 | // Раскомментируй после объявления объекта. 16 | // @JvmStatic 17 | // fun main(args: Array) { 18 | // TODO 3: Создай экземпляр класса "VideoGame". 19 | // Создай копию игры с помощью функции ата класса ".copy()", сохрани копию в другой переменной. 20 | // val game = 21 | // val copy = 22 | 23 | // TODO 4: Выведи в консоль результат сравнения игры и её копии, используя оператор сравнения "==". 24 | // Результат должен быть типа Boolean "true". 25 | // val equal = false 26 | // println("Objects are equal $equal") 27 | 28 | // TODO 5: Создай массив игр. В момент создания, наполни его несколькими играми и массив в консоль. 29 | // val games = arrayOf(game, copy, ...) 30 | // games.forEach { 31 | // // print 32 | // } 33 | // } 34 | //} 35 | 36 | 37 | 38 | /* Бонусные задания */ 39 | 40 | // TODO 6: Создай "enum class", назови его "Genre", добавь в него несколько вариантов значений. 41 | // Добавь его, как новое свойство класса "VideoGame". 42 | // Поправь созданные сущности видеоигр в коде коде воркшопа. 43 | // Запусти выполнение функции "main()" и посмотри результат. 44 | /* 45 | ... Genre { 46 | ..., 47 | ..., 48 | ... 49 | } 50 | * */ 51 | 52 | // TODO 7: Добавь новое свойство класса "VideoGame", присвой ему значение "по-умолчанию". 53 | // Как ты можешь убедиться, новое свойство со значением "по-умолчанию" не требует делать исправлений в таком коде. 54 | // Но надо помнить, что поведение созданных сущностей может измениться. 55 | // Запусти выполнение функции "main()" и посмотри результат. -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop7.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("UNUSED_VARIABLE") 2 | 3 | package day_1_kotlin.langrus.assignments 4 | 5 | // Workshop #7 - list, mutable list, useful functions, maps 6 | 7 | object KotlinWorkshop7 { 8 | 9 | @JvmStatic 10 | fun main(args: Array) { 11 | 12 | // Не исправляй! Дано: 13 | val poem = arrayOf( 14 | "Истинное счастье доступно", 15 | "Лишь только тогда, когда всё хорошо", 16 | "Я не верю что добро существует", 17 | "На самом деле", 18 | "Реальность", 19 | "Определяет", 20 | "Восприятие", 21 | "Ничто мне неподвластно", 22 | "И я никогда не скажу что", 23 | "Сегодня был прекрасный день" 24 | ) 25 | 26 | 27 | 28 | /* Рабочая зона */ 29 | 30 | // TODO 1: Распечатай "poem" в двух вариантах: 31 | // 1. Только отфильтрованные строки длиной короче 12 символов; 32 | // 2. Все строки в обратном порядке. 33 | /* 34 | val filtered = ... 35 | val reversed = ... 36 | println(filtered) 37 | reversed.forEach { println(it) } 38 | println(reversed) 39 | * */ 40 | 41 | // TODO 2: Раскомментируй. 42 | // Инициализируй переменную с коллекцией чисел "evenList" 43 | // и добавь в неё только чётные числа в диапазоне от 0 до 50, включая 0. 44 | /* 45 | val evenList = ... 46 | for (i in 0..50) { 47 | } 48 | println(evenList) 49 | */ 50 | 51 | 52 | 53 | // Не исправляй! Дано: 54 | val weatherMap = mutableMapOf( 55 | "Moscow" to 2, 56 | "St. Petersburg" to -1, 57 | "Minsk" to 4 58 | ) 59 | 60 | 61 | 62 | /* Бонусные задания */ 63 | 64 | // TODO 3. В погодную карту "weatherMap" добавь погоду в "Kiev" и в "Tel-Aviv". 65 | // weatherMap... = 66 | 67 | // TODO 4. Отфильтруй и выведи в консоль города с погодой выше +0С. 68 | // Вызывай операторы один за другим, в виде "цепи" (chaining operators). 69 | // weatherMap 70 | } 71 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop8.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("MayBeConstant", "unused", "UNUSED_VARIABLE") 2 | 3 | package day_1_kotlin.langrus.assignments 4 | // workshop #8 - const, companion object, extension func* 5 | 6 | /* 7 | * Сокращаем телефон до максимально докустимой длины maxLength 8 | * и пишем функцию экстеншен на лист, которая заменяет каждый i-й элемент номером телефона 9 | */ 10 | 11 | // TODO 1: make maxLength const that is visible only inside the Person class 12 | val maxLength = 12 13 | 14 | // TODO 2: make companionConstant part of companion object 15 | val companionConstant = 12 16 | 17 | class Person(phoneCode: String) { 18 | 19 | val code = if (phoneCode.length > maxLength) phoneCode.subSequence(0, maxLength) else phoneCode 20 | 21 | companion object { 22 | // TODO 2 23 | } 24 | 25 | // * * * Bonus task * * * (work on home) 26 | 27 | //TODO 3: make this fun as extension to a list outside the Person class 28 | private fun replacePlacesWithThePhoneCode(list: List, placeNum: Int = 3): List { 29 | return list.mapIndexed { index, any -> if (index % placeNum == 0) code else any} 30 | } 31 | } 32 | 33 | fun main(){ 34 | val list = mutableListOf("1", 3, 4, "Patrick", 3.4, "123-59") 35 | 36 | val p = Person("45-45-45") 37 | 38 | 39 | // TODO: uncomment after finishing TODO 1 40 | // println(Person.maxLength) 41 | 42 | //TODO *: uncomment after doing function 43 | // lst.replacePlacesWithThePhoneCode(p, 4) 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/assignments/KotlinWorkshop9.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("unused") 2 | 3 | package day_1_kotlin.langrus.assignments 4 | 5 | // workshop #9 - generics 6 | /* 7 | * Класс программиста, который может учить и забывать концепты на определенном языке. 8 | */ 9 | 10 | fun main() { 11 | val p = Programmer() 12 | 13 | //TODO: uncomment all 14 | // p.learn(Kotlin("basics")) 15 | // 16 | // p.learn(Kotlin("generics")) 17 | // p.learn(Kotlin("coroutines")) 18 | 19 | println(p.howManyConceptsDoIKnow()) 20 | // should be equal to 3 21 | 22 | println(p.lastConcept()) 23 | //should be Kotlin(element=coroutines) 24 | 25 | // p.forget(Kotlin("generics")) 26 | println(p.howManyConceptsDoIKnow()) 27 | // should be equal to 2 28 | } 29 | 30 | 31 | class Programmer { 32 | 33 | fun howManyConceptsDoIKnow(): Int = TODO() 34 | 35 | // TODO: add "learn" function with new concept 36 | 37 | //TODO: add "forget" function with one concept to forget 38 | 39 | fun lastConcept(): T = TODO() 40 | } 41 | 42 | interface Language{ 43 | val element: String 44 | } 45 | 46 | data class JavaLanguage(override val element: String) : Language 47 | data class Kotlin(override val element: String): Language 48 | data class Swift(override val element: String): Language 49 | data class C_Sharp(override val element: String): Language 50 | -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/info/A_HowToComment.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.info 2 | 3 | /** 4 | * Такой комментарий называется "java-doc". В него помещают описание классов, функций, полей и т.п. 5 | * Чтобы увидеть, есть ли у класса описание, помести курсор на имя нужного класса [A_HowToComment] и зажми Ctrl+Q. 6 | */ 7 | object A_HowToComment { 8 | 9 | // Закомментированный код игнорируется компилятором. 10 | 11 | // Как делать комментарии: 12 | 13 | // 1. Используй двойной slash "//" символ в начале строки. Это будет однострочный комментарий: 14 | // val commented = "ignored" 15 | // Закомментируй следующую строку. Помести курсор в любом месте строки и зажми комбо "Ctrl+/" 16 | val plzCommentMe = "null" 17 | 18 | // 2. Можно делать контекстные комментарии внутри строк, для этого окружи кусок кода используя /* */ 19 | val commented = /*"ignored"*/ "not ignored" 20 | 21 | // Чтобы сделать многострочный комментарий, окружи код с помощью /* */. 22 | // Такой коммент может выглядеть по разному, но суть от этого не изменится. 23 | // 3a. Вид1 24 | /* 25 | * val firstLine = "ignored" 26 | * val secondLine = "ignored" 27 | * */ 28 | 29 | // 3b. Вид2 30 | /* 31 | val firstLine = "ignored" 32 | val secondLine = "ignored" 33 | */ 34 | 35 | // 4. Также, есть специальные слова, зарезервированные для определённого контроля кода. Вот самые распространённые: 36 | // Но не стоит ими злоупотреблять, т.к. многие команды разработчиков устанавливают свой code-style 37 | // и по-своему реагируют на наличие таких комментов (и комментов вообще). 38 | // Также может быть настроена автосборка проекта с учётом наличия таких слов. 39 | // TODO 40 | // FIXME 41 | // i.e. FIXME AuthorName 10/26/2020: have to refactor something 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/info/B_HowToRunProgram.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.info 2 | 3 | object B_HowToRunProgram { 4 | 5 | // Точкой входа исполняемой программы является функция "main". 6 | // Это статическая функция и она имеет зарезервированный синтаксис. 7 | 8 | // Внутри класса или объекта, где ещё нет main() функции, начни писать "ma" и подожди. 9 | // Среда разработки Intellij Idea предложит тебе авто-дополнить вводимый код с помощью шортката "maino". 10 | 11 | // Когда увидишь предложение дополнить код, нажми "Enter": 12 | @JvmStatic 13 | fun main(args: Array) { 14 | // Собрать проект и запустить программу можно из верхнего меню "Run", или зажав "Ctrl+Shift+F10". 15 | // Или нажав на зелёный треугольник на полях, слева от кода, возле объявления функции main(), см. строку 13. 16 | } 17 | 18 | // Можно проверить некоторый код, не создавая функции main(). 19 | // Запусти тестовую среду Котлина: в верхнем меню перейди в "Tools -> Kotlin -> Kotlin REPL". 20 | // Кликни в области открывшегося снизу окна консоли. Можешь ввести код там, а для исполнения зажать "Ctrl+Enter". 21 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/info/C_HowToPrintResults.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.info 2 | 3 | import java.util.logging.Logger 4 | 5 | object C_HowToPrintResults { 6 | 7 | // Для того, чтобы увидеть результат в консоли используйте стандартные методы ввода вывода 8 | // и/или классы для логирования из SDK: функции print(), println() или logger 9 | 10 | // Консоль находится во вкладке "Run" в нижнем меню Intellij idea. 11 | 12 | @JvmStatic 13 | fun main(args: Array) { 14 | println("message") // Строка 15 | println("message " + "other") // Конкатенация строк 16 | println("message " + 1) // Конкатенация разных объектов 17 | 18 | val value = "value" 19 | println("message $value") // Placeholder - заглушка для вывода результата при написании его напрямую в строке 20 | 21 | println("message ${Results().property}") // Placeholder с вычисляемым значением 22 | 23 | println("message value:" + value + ", property:${Results().property}") 24 | 25 | println(""" 26 | |long 27 | |formatted 28 | |message 29 | """.trimIndent()) 30 | 31 | try { 32 | // Код с ошибкой 33 | } catch (expected: Exception) { 34 | val log = Logger.getLogger("MyWorkshopLogger") 35 | log.throwing("Current class name", "someMethod()", expected) 36 | } 37 | } 38 | 39 | class Results { 40 | val property = "property" 41 | } 42 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/info/D_HowToUseHotkeys.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.info 2 | 3 | object D_HowToUseHotkeys { 4 | 5 | /* 6 | * В "Intellij idea" и "Android studio" добавлено множество шаблонов, ключевых слов и горячих клавиш. 7 | * Всё это может быть гибко настроено и позволяет существенно ускорить написание стандартных частей кода. 8 | * Вот некоторые сочетания горячих клавиш, которые могут вам помочь в повседневной работе: 9 | * */ 10 | 11 | // Для быстрого перемещения по местам вызова функции или переменной, 12 | // помести курсор на название нужного объекта и зажми "Ctrl+B" 13 | private fun jumpToMethod() { 14 | } 15 | 16 | // Для быстрого перемещения к месту, где ты в последний раз модифицировал код, 17 | // зажми "Ctrl+Shift+Backspace". 18 | // ---> Напиши что-нибудь рядом, пролистай текст до конца и зажми комбо. 19 | 20 | // Чтобы запомнить несколько мест в коде, в пределах проекта, помести курсор на нужную 21 | // строку и зажми "Ctrl+Shift+[1..9]". Где цифра - это номер сохранённого места. 22 | // Для быстрого перемещения между закладками зажми "Ctrl+[1..9]". 23 | // Чтобы переназначить или удалить закладку, используй тот же номер в другом месте, 24 | // или там где находишься сейчас зажми комбо "Ctrl+Shift+[1..9]" два раза подряд. 25 | 26 | // Для быстрого перемещения между строками зажми "Ctrl+G" (go to the line). 27 | // В диалоговом окне введи номер. 28 | 29 | // Чтобы посмотреть пояснение к классу, функции. Увидеть, какие аргументы принимаются на вход, что возвращается, 30 | // какое описание. Помести курсор на названии интересующего объекта и зажми "Ctrl+Q". 31 | private fun seeTheArgTypes() { 32 | hiddenArgsContainer(1, "2", 3) 33 | } 34 | 35 | // При вводе текста можно посмотреть предложенные варианты авто-дополнения. 36 | // Для этого, начни вводить код и зажми "Ctrl+Space" или "Alt+Enter". 37 | // "Alt+Enter" также может содержать подходящий вариант решения ошибки синтаксиса. 38 | 39 | // Чтобы быстро скопировать строку целиком, в любом месте строки зажми "Ctrl+C". 40 | 41 | // Чтобы быстро скопировать и вырезать строку целиком, в любом месте строки зажми "Ctrl+X". 42 | 43 | // Чтобы продублировать строку, в любом месте строки зажми "Ctrl+D". 44 | 45 | // Чтобы вставить строку ниже текущей с перемещением курсора, в любом месте текущей строки зажми "Shift+Enter". 46 | 47 | // Чтобы менять местами строки, зажми "Alt+Shift" и не отпуская используй стрелки клавиатуры вверх, вниз. 48 | 49 | @JvmStatic 50 | fun main(args: Array) { 51 | jumpToMethod() 52 | } 53 | 54 | /** 55 | * Пример для демонстрации Ctrl+Q 56 | */ 57 | private fun hiddenArgsContainer(a: Int, b: String, c: Any): String { 58 | return "" 59 | } 60 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop1.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("RedundantNullableReturnType", "RedundantExplicitType", "UNUSED_VARIABLE") 2 | 3 | package day_1_kotlin.langrus.solutions 4 | 5 | import java.util.* 6 | 7 | // Практическая работа #1 - val, var, null, kotlin null безопасность, Элвис оператор 8 | 9 | object KotlinWorkshop1 { 10 | 11 | @JvmStatic 12 | fun main(args: Array) { 13 | 14 | // Инициализация переменных. Обрати внимание, они могут принимать значение null. 15 | // Не исправляй! Дано: 16 | val nullableElvisString: String? = null 17 | val nullableAssertionString: String? = "потенциально null" 18 | val emptyString = "" 19 | 20 | 21 | /* Рабочая зона */ 22 | 23 | // TODO 1: Раскомментируй. 24 | // Если "nullableElvisString" равно null, сделай значение "notNullUserString" равным значению пустой строки "emptyString". 25 | // Присвой "notNullUserString" значение из "nullableElvisString". Исправиь присвоение используя Элвис-оператор. 26 | // Исправить присвоение используя Элвис-оператор "?:". 27 | var notNullUserString: String = nullableElvisString ?: emptyString 28 | println("Строка результат пустая $notNullUserString") 29 | 30 | // TODO 2: Раскомментируй. 31 | // По факту мы знаем, что значение "nullableAssertionString" не равно null. 32 | // Сделай принудительное присвоение используя !! оператор. 33 | notNullUserString = nullableAssertionString!! 34 | println("Строка результат равна $notNullUserString") 35 | 36 | 37 | /* Бонусные задания */ 38 | 39 | // TODO 3: Раскомментируй. Сложи две переменные. 40 | // Если firstNumber равно null, сумма должна быть null. Если secondNumber равно null, сумма должна быть равна значение firstNumber. 41 | // Используй проверку на null '?', для сложения используй функцию '.plus()'. Внутри '.plus()' используй '?:'. 42 | val notNullAlternative = 0 43 | val firstNumber: Int? = 10 44 | val secondNumber: Int? = 20 45 | val sum: Int? = firstNumber?.plus(secondNumber ?: notNullAlternative) 46 | println("Сумма равна {$sum}") 47 | 48 | 49 | // TODO 4: Раскомментируй. Сохрани строку введённую с клавиатуры в переменную "stringInput". 50 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 51 | // Кликни в зоне открытого окна и введи строку. 52 | print("Пожалуйста введите строку: ") 53 | val stringInput: String? = MyScanner.scan.next() // <--- string input 1 54 | 55 | // TODO 5: Раскомментируй. 56 | // Сохрани значения чисел введённух с клавиатуры в переменные "firstIntInput" и "secondIntInput". 57 | // Сохраните сумму введенных чисел в "sumIntInputs". Вместо потенциального 'null' подставьте значение по умолчанию. 58 | // Используй проверку на null '?', для сложения используй функцию '.plus()'. Внутри '.plus()' используй '?:'. 59 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 60 | // Кликни в зоне открытого окна и введи строку. 61 | print("Пожалуйста введите первое число: ") 62 | val firstIntInput: Int? = MyScanner.scan.nextInt() // <--- вводим первое число 63 | print("Пожалуйста введите второе число: ") 64 | val secondIntInput: Int? = MyScanner.scan.nextInt() // <--- вводим второе число 65 | val sumIntInputs: Int? = firstIntInput?.plus( 66 | secondIntInput ?: notNullAlternative 67 | ) // <--- делаем замену потенциального 'null' значением по умолчанию 68 | println("Исходная строка: $stringInput, Сумма чисел: $sumIntInputs") 69 | 70 | 71 | /* Примеры */ 72 | 73 | val number: Int = -1 74 | val someNumber: Double = 2.5 75 | val someString: String = "Привет, мир!" 76 | val someFlag: Boolean = true 77 | var someNullableNumber: Long? = null 78 | } 79 | } 80 | 81 | 82 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 83 | 84 | class MyScanner { 85 | companion object { 86 | val scan = Scanner(System.`in`) 87 | } 88 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop2.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress( 2 | "UNREACHABLE_CODE", 3 | "DuplicatedCode", 4 | "UNUSED_VARIABLE", 5 | "ControlFlowWithEmptyBody", 6 | "ConstantConditionIf" 7 | ) 8 | 9 | package day_1_kotlin.langrus.solutions 10 | 11 | import java.util.* 12 | import kotlin.random.Random 13 | 14 | // Практическая работа #2 - control flow (if, when), arrays, for loop, if expression, return & jumps 15 | 16 | object KotlinWorkshop2 { 17 | 18 | // Запусти исполнение main() функции, для выполнения кода. 19 | // См. подробнее в /../info/B_HowToRunProgram 20 | @JvmStatic 21 | fun main(args: Array) { 22 | 23 | 24 | 25 | /* Рабочая зона */ 26 | 27 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 28 | // Кликни в зоне открытого окна и введи строку. 29 | // Не исправляй! Дано: 30 | val upperBound = getUpperBound() 31 | val nonNullUpperBound = upperBound ?: 10 32 | val randomNumber = Random.nextInt(nonNullUpperBound) 33 | val scanner = Scanner(System.`in`) 34 | 35 | while (true) { 36 | // TODO 1: Напиши логику сравнения "userInput" с "randomNumber" используя If-Else выражение. 37 | // Когда ввод с клавиатуры равен значению "randomNumber", прерви бесконечный цикл while 38 | // используя ключевое слово "break" и выведи сообщение "Поздравляю! Задуманное число х" 39 | // Если введено число меньше "randomNumber", выведи сообщение "Ваше число меньше задуманного, пожалуйста продолжаем." 40 | // Если введено число больше "randomNumber", выведи сообщение "Ваше число больше задуманного, пожалуйста продолжаем." 41 | 42 | print("Введите число в диапазоне 0..$nonNullUpperBound включительно: ") 43 | // Сохраняем введённое с клавиатуры число в "userInput". 44 | val userInput: Int = scanner.nextInt() 45 | if (userInput == randomNumber) { 46 | println("Поздравляю! Задуманное число равно $randomNumber!") 47 | break 48 | 49 | } else if (userInput > randomNumber) { 50 | println("Ваше число больше задуманного, пожалуйста продолжаем.") 51 | 52 | } else { 53 | println("Ваше число меньше задуманного, пожалуйста продолжаем.") 54 | } 55 | } 56 | 57 | 58 | 59 | /* Бонусные задания */ 60 | 61 | // TODO 2: Раскомментируй. Проинициализируй "numbersArray". 62 | // "numbersArray" это массив целочисленных значений, длинной 5 чисел. 63 | val numbersArray = intArrayOf(0, 0, 0, 0, 0) 64 | println("\nДан массив:") 65 | for ((index, number) in numbersArray.withIndex()){ 66 | println("$index $number") 67 | } 68 | 69 | // TODO 3: Раскомментируй. Проинициализируй свойство "size" длинной массива "numbersArray". 70 | // Измени условия повтора бесконечного цикла while так, чтобы он стал конечным и выполнился не более "size" раз. 71 | println("\nПрограмма 2. \"Введите коллекцию чисел\"") 72 | val size = numbersArray.size 73 | var counter = 0 74 | while (counter < size) { 75 | print("Введите число в диапазоне 0..10 включительно: ") 76 | val userInput: Int = scanner.nextInt() 77 | 78 | // TODO 4: Сохрани и добавь введённые с клавиатуры числа в массив "numbersArray" согласно следующей логики: 79 | // - Если введено 3 - добавь число в массив без изменений; 80 | // - Если введено 5 - умнож и добавь (5 * size); 81 | // - Если введено 9 - сложи и добавь (2 + size); 82 | // - Иначе не добавляй ничего. 83 | // Используй выражение "When". 84 | when (userInput) { 85 | 3 -> numbersArray.set(counter, userInput) 86 | 5 -> numbersArray.set(counter, userInput * size) 87 | 9 -> numbersArray.set(counter, 2 + size) 88 | else -> { /* ignored */ } 89 | } 90 | 91 | counter++ 92 | } 93 | 94 | // TODO 5: Выведи в консоль значения элементов массива и индекс, на котором они находятся. 95 | // Новый элемент на новой строке. Это должно выглядеть как "индекс: значение". 96 | for ((index, number) in numbersArray.withIndex()){ 97 | println("$index: $number") 98 | } 99 | } 100 | 101 | 102 | 103 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 104 | 105 | private fun getUpperBound(): Int? { 106 | println("Программа 1. \"Угадай число\"") 107 | print("Введите число максимум в диапазоне 10..20 включительно: ") 108 | val scanner = Scanner(System.`in`) 109 | return try { 110 | scanner.nextInt() 111 | 112 | } catch (e: InputMismatchException) { 113 | null 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop3.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | import java.util.* 4 | import java.util.logging.Logger 5 | import kotlin.random.Random 6 | 7 | // Workshop #3 - functions, lambda, high-order function 8 | 9 | object KotlinWorkshop3 { 10 | 11 | // Запусти исполнение main() функции, для выполнения кода. 12 | // См. подробнее в /../info/B_HowToRunProgram 13 | @JvmStatic 14 | fun main(args: Array) { 15 | 16 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 17 | // Не исправляй! Дано: 18 | val scanner = Scanner(System.`in`) 19 | val upperBound = getUpperBound(scanner) 20 | val nonNullUpperBound = upperBound ?: 10 21 | val randomNumber = Random.nextInt(nonNullUpperBound) 22 | val capacity = nonNullUpperBound 23 | val guesses = createIntArrayOfCapacity(capacity) 24 | 25 | 26 | 27 | /* Рабочая зона */ 28 | 29 | var guessed = false 30 | var counter = 0 31 | while (!guessed && counter < capacity) { 32 | print("Input a number in range 0..$nonNullUpperBound inclusive: ") 33 | // Когда программа запущена, ввод с клавиатуры ожидается внизу, во вкладке RUN. 34 | val userInput: Int = getNextInput(scanner, nonNullUpperBound) 35 | guesses[counter] = userInput 36 | 37 | // TODO 1: Раскомментируй. 38 | // Объяви функцию "playRound": она должна принимать на вход два Int аргумента и возвращать Boolean. 39 | // См. ниже. 40 | guessed = playRound(userInput, randomNumber) 41 | 42 | counter++ 43 | } 44 | 45 | // TODO (bonus): Напиши аналитическцую систему для игрового раунда, 46 | // которая будет собирать статистику и печатать результат. См. ниже. 47 | printGameStats(guesses, counter, randomNumber) 48 | } 49 | 50 | // TODO 1: Раскомментируй. 51 | // Объяви функцию "playRound": она должна принимать на вход два Int аргумента и возвращать Boolean. 52 | // TODO 2: Функция возвращает "true" и выводит сообщение "Congratulations!", 53 | // когда ввод с клавиатуры равен значению "randomNumber"; 54 | // Если введено число больше "randomNumber", выведи сообщение "Your Guess is higher, continue." и верни false; 55 | // Если введено число меньше "randomNumber", выведи сообщение "Your Guess is lower, continue." и верни false. 56 | // Можно использовать наработки из workshop 2, с отличием, что здесь это вынесенная функция, нет цикла и возвращает результат. 57 | private fun playRound(userInput: Int, randomNumber: Int): Boolean { 58 | when { 59 | userInput == randomNumber -> { 60 | println("Congratulation, it was $randomNumber!") 61 | return true 62 | } 63 | userInput > randomNumber -> { 64 | println("Your Guess is higher, continue.") 65 | } 66 | else -> { 67 | println("Your Guess is lower, continue.") 68 | } 69 | } 70 | 71 | return false 72 | } 73 | 74 | 75 | 76 | /* Бонусные задания */ 77 | 78 | // TODO (bonus): Напиши аналитическцую систему для игрового раунда, 79 | // которая будет собирать статистику и печатать результат. См. ниже. 80 | private fun printGameStats(guesses: IntArray, guessCounter: Int, randomNumber: Int) { 81 | // TODO 3: Раскомментируй. Выведи общее число попыток ввода. 82 | printTotalCountOfGuesses(guessCounter) 83 | 84 | // TODO 4: Раскомментируй. 85 | // Напиши функцию высшего порядка "countHigherGuesses" для вывода всех попыток воода, которые оказались выше "randomNumber". 86 | // Функция должна возвращать число таких попыток как результат. 87 | countHigherGuesses(guesses, randomNumber) { counter -> 88 | println("Total count of higher guesses: $counter\n") 89 | } 90 | 91 | // TODO 5: Раскомментируй. 92 | // Напиши lambda-выражение "countLowerGuesses" для вывода всех попыток воода, которые оказались ниже "randomNumber". 93 | // И не равны значению "-1", заданному элементу массива при инициализации массива. 94 | countLowerGuesses(guesses, randomNumber) 95 | 96 | // TODO 6: Раскомментируй. 97 | // Выведи результаты всех попыток ввода, строка за строкой. 98 | // Используй функцию высшего порядка ".forEach". 99 | println("All guesses:") 100 | guesses.forEach { 101 | print("$it, ") 102 | } 103 | } 104 | 105 | // TODO 3 106 | private fun printTotalCountOfGuesses(guessCounter: Int) { 107 | println("\nTotal count: $guessCounter\n") 108 | } 109 | 110 | // TODO 4 111 | private fun countHigherGuesses( 112 | guesses: IntArray, 113 | randomNumber: Int, 114 | printer: (Int) -> Unit 115 | ): Int { 116 | 117 | var counter = 0 118 | for (guess in guesses) { 119 | if (guess > randomNumber) { 120 | counter++ 121 | println("$counter) $guess is higher than $randomNumber") 122 | } 123 | } 124 | 125 | printer(counter) 126 | 127 | return counter 128 | } 129 | 130 | // TODO 5 131 | val countLowerGuesses: (IntArray, Int) -> Unit = { guesses, randomNumber -> 132 | var counter = 0 133 | for (guess in guesses) { 134 | if (guess != -1 && guess < randomNumber) { 135 | counter++ 136 | println("$counter) $guess is lower than $randomNumber") 137 | } 138 | } 139 | 140 | println("Total count of lower guesses: $counter\n") 141 | } 142 | 143 | 144 | 145 | /* Для корректного прогона воркшопа не модифицируй утилиты ниже */ 146 | 147 | private fun getUpperBound(scanner: Scanner): Int? { 148 | val upperLimit = 20 149 | val lowerLimit = 1 150 | 151 | println("Game: \"Guess a number\"") 152 | print("Enter maximum number in range 1..20 inclusive: ") 153 | return try { 154 | var input = scanner.nextInt() 155 | if (input in lowerLimit..upperLimit) { 156 | input 157 | 158 | } else { 159 | println("Wrong number. Use default as limit: $upperLimit") 160 | upperLimit 161 | } 162 | 163 | } catch (e: InputMismatchException) { 164 | null 165 | } 166 | } 167 | 168 | private fun getNextInput(scanner: Scanner, nonNullUpperBound: Int): Int { 169 | val lowerLimit = 0 170 | val badResult = -1 171 | 172 | return try { 173 | var input = scanner.nextInt() 174 | if (input in lowerLimit..nonNullUpperBound) { 175 | input 176 | 177 | } else { 178 | println("Wrong input. Should be $nonNullUpperBound or lower.") 179 | badResult 180 | } 181 | 182 | } catch (e: InputMismatchException) { 183 | val log = Logger.getLogger("KotlinWorkshop3Logger") 184 | log.throwing("KotlinWorkshop3Logger", "getNextInput()", e) 185 | badResult 186 | } 187 | } 188 | 189 | private fun createIntArrayOfCapacity(capacity: Int): IntArray { 190 | return IntArray(capacity) { i -> -1 } 191 | } 192 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop4.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // Workshop #4 - classes 4 | 5 | object KotlinWorkshop4 { 6 | 7 | // Не исправляй! Дано: 8 | @JvmStatic 9 | fun main(args: Array) { 10 | testBus() 11 | } 12 | 13 | 14 | 15 | /* Рабочая зона */ 16 | 17 | // TODO 1: Объяви класс "Bus" который в качестве аргумента будет получать число "passengersCount". 18 | // ? Хорошим тоном считается объявлять классы и интерфейсы внизу файла, под функциями. 19 | // Здесь, и в других частях практической работы, классы и функции отсортированы по порядку выполнения заданий. 20 | class Bus(private val passengersCount: Int) { 21 | 22 | // TODO 2: Добавь функцию "drive", без аргументов. 23 | // Она должна выводить фразу "Driving N passengers to the destination", где N - число пассажиров. 24 | fun drive() { 25 | println("Driving $passengersCount passengers to the destination") 26 | } 27 | } 28 | 29 | private fun testBus() { 30 | // TODO 3: Создайте экземпляр класса "Bus". 31 | val bus = Bus(10) 32 | 33 | // TODO 4: Отправь автобус к пункту назначения и проверь, что выведется в консоль. 34 | bus.drive() 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop5.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // Workshop #5 - inheritance, abstract, interface 4 | 5 | // Не исправляй! Дано: 6 | // Объявляем контракт, представляющий некое свойство транспорта. 7 | interface Driveable { 8 | fun drive() 9 | } 10 | 11 | // Объявляем класс пассажирского транспорта вцелом. 12 | // Придадим такому транспорту свойство перемещаться под управлением водителя. 13 | abstract class Transport(protected var passengersCount: Int): Driveable 14 | 15 | // Создадим реальный транспорт: "Велосипед". Он может управляться водителем и перевозит одного пассажира. 16 | class Bicycle: Transport(1) { 17 | override fun drive() { 18 | println("Ride a bicycle.") 19 | } 20 | } 21 | 22 | 23 | 24 | /* Рабочая зона */ 25 | 26 | // TODO 1: Создай свой интерфейс - контракт, который бы также подошел по смыслу классу транспорт. 27 | // См. ниже. 28 | // ? Имена классов и файлов Котлин принято называть с заглавной буквы, в формате "camelCase". 29 | // Например: "SomeLongClassName" 30 | interface Fuelable { 31 | fun isFull(): Boolean 32 | fun fuel() 33 | } 34 | 35 | // TODO 2: Создай свои собственные классы, например "Bus" и "Car". 36 | // Эти классы не будут полностью написаны с нуля, они должны расширять общий класс "Transport", 37 | // и дополнительно реализовывать придуманный тобой интерфейс. 38 | // ? Класс может наследовать только один класс, но реализовывать несколько интерфейсов, например: 39 | // class Kitty(): Cat, Cuteable, Sleepable, Furryable {} 40 | class Bus(passengersCount: Int): Transport(passengersCount), Fuelable { 41 | 42 | private var hasFuel = false 43 | 44 | override fun drive() { 45 | if (isFull()) { 46 | hasFuel = false 47 | println("Driving $passengersCount passengers to the destination") 48 | 49 | } else { 50 | println("Don't have fuel. Hey passengers, let's push this thing together!") 51 | } 52 | } 53 | 54 | override fun isFull(): Boolean = hasFuel 55 | 56 | override fun fuel() { 57 | hasFuel = true 58 | println("Fueled a bit!") 59 | } 60 | } 61 | 62 | // TODO 2: Создай свои собственные классы, например "Bus" и "Car". 63 | // Эти классы не будут полностью написаны с нуля, они должны расширять общий класс "Transport", 64 | // и дополнительно реализовывать придуманный тобой интерфейс. 65 | class Car(passengersCount: Int): Transport(passengersCount), Fuelable { 66 | 67 | private var hasFuel = false 68 | 69 | override fun drive() { 70 | if (isFull()) { 71 | println("Driving a car with a speed of light! $passengersCount passengers on board.") 72 | hasFuel = false 73 | 74 | } else { 75 | println("Don't have fuel.") 76 | } 77 | } 78 | 79 | override fun isFull(): Boolean = hasFuel 80 | 81 | override fun fuel() { 82 | hasFuel = true 83 | println("Filled up with gasoline!") 84 | } 85 | } 86 | 87 | // TODO 3: Протестируй работоспособность твоего транспорта. 88 | object VehiclesTest { 89 | 90 | // Запусти исполнение main() функции, для выполнения кода. 91 | @JvmStatic 92 | fun main(args: Array) { 93 | testBus() 94 | testCar() 95 | testBicycle() 96 | 97 | testBusParts() 98 | } 99 | 100 | private fun testBus() { 101 | println("\nTesting how bus drives...") 102 | val bus = Bus(10) 103 | bus.drive() 104 | bus.fuel() 105 | bus.drive() 106 | } 107 | 108 | private fun testCar() { 109 | println("\nTesting how car drives...") 110 | val car = Car(4) 111 | car.drive() 112 | car.fuel() 113 | car.drive() 114 | } 115 | 116 | private fun testBicycle() { 117 | println("\nTesting how bicycle drives...") 118 | val bicycle = Bicycle() 119 | bicycle.drive() 120 | } 121 | 122 | 123 | 124 | /* Бонусные задания */ 125 | 126 | // TODO 4: Протестируй агрегаты автобуса, как независимые компоненты. 127 | // Т.е. каждый набор независимых свойств - отдельно, чтобы в тестируемой сущности были скрыты все свойства, 128 | // не принадлежащие к данному набору. 129 | private fun testBusParts() { 130 | val bus = Bus(0) 131 | 132 | val engine: Driveable = bus 133 | println("\nTesting bus's engine:") 134 | println(engine.drive()) 135 | 136 | val pump: Fuelable = bus 137 | println("\nTesting bus's fuel system:") 138 | println("has fuel: ${pump.isFull()}") 139 | println(pump.fuel()) 140 | println("has fuel: ${pump.isFull()}") 141 | } 142 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop6.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // Workshop #6 - special classes, objects, data classes 4 | 5 | 6 | 7 | /* Рабочая зона */ 8 | 9 | // TODO 1: Добавь в data class 2-4 свойства. 10 | data class VideoGame( 11 | val name: String, 12 | val year: Int, 13 | val genre: Genre /* добавится только после TODO 6 */, 14 | val rate: Int = 5 /* добавится только после TODO 7 */ 15 | ) 16 | 17 | // TODO 2: Создай объект "VideoGamesTest", который будет использоваться для тестирования игр. 18 | object VideoGameTest { 19 | 20 | @JvmStatic 21 | fun main(args: Array) { 22 | // TODO 3: Создай экземпляр класса "VideoGame". 23 | // Создай копию игры с помощью функции ата класса ".copy()", сохрани копию в другой переменной. 24 | val game = VideoGame("Heroes of Might and Magic III", 1999, Genre.STRATEGY) 25 | val copy = game.copy() 26 | 27 | // TODO 4: Выведи в консоль результат сравнения игры и её копии, используя оператор сравнения "==". 28 | // Результат должен быть типа Boolean "true". 29 | val equal = game == copy 30 | println("Objects are equal $equal") 31 | 32 | // TODO 5: Создай массив игр. В момент создания, наполни его несколькими играми и массив в консоль. 33 | val games = arrayOf( 34 | game, 35 | game.copy(name = "Heroes 4", year = 2002), 36 | VideoGame("NFS", 2000, Genre.RACING) 37 | ) 38 | games.forEach { 39 | println(it) 40 | } 41 | 42 | 43 | 44 | /* Примеры */ 45 | 46 | // TODO 6, TODO 7 47 | val dn3d = VideoGame( 48 | name = "Duke Nukem 3D", 49 | year = 1996, 50 | genre = Genre.ACTION 51 | ) 52 | println("\n" + dn3d) 53 | } 54 | } 55 | 56 | 57 | 58 | /* Бонусные задания */ 59 | 60 | // TODO 6: Создай "enum class", назови его "Genre", добавь в него несколько вариантов значений. 61 | // Добавь его, как новое свойство класса "VideoGame". 62 | // Поправь созданные сущности видеоигр в коде коде воркшопа. 63 | // Запусти выполнение функции "main()" и посмотри результат. 64 | enum class Genre { 65 | STRATEGY, 66 | RACING, 67 | ACTION 68 | } 69 | 70 | // TODO 7: Добавь новое свойство класса "VideoGame", присвой ему значение "по-умолчанию". 71 | // Как ты можешь убедиться, новое свойство со значением "по-умолчанию" не требует делать исправлений в таком коде. 72 | // Но надо помнить, что поведение созданных сущностей может измениться. 73 | // Запусти выполнение функции "main()" и посмотри результат. -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop7.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // Workshop #7 - list, mutable list, useful functions, maps 4 | 5 | object KotlinWorkshop7 { 6 | 7 | @JvmStatic 8 | fun main(args: Array) { 9 | 10 | // Не исправляй! Дано: 11 | val poem = arrayOf( 12 | "Истинное счастье доступно", 13 | "Лишь только тогда, когда всё хорошо", 14 | "Я не верю что добро существует", 15 | "На самом деле", 16 | "Реальность", 17 | "Определяет", 18 | "Восприятие", 19 | "Ничто мне неподвластно", 20 | "И я никогда не скажу что", 21 | "Сегодня был прекрасный день" 22 | ) 23 | 24 | 25 | 26 | /* Рабочая зона */ 27 | 28 | // TODO 1: Распечатай "poem" в двух вариантах: 29 | // 1. Только отфильтрованные строки длиной короче 12 символов; 30 | // 2. Все строки в обратном порядке. 31 | val filtered = poem.filter { it.length < 12 } 32 | val reversed = poem.reversed() 33 | println("\nFiltered: $filtered") 34 | println("\nReversed:") 35 | reversed.forEach { println(it) } 36 | println("\n") 37 | 38 | // TODO 2: Раскомментируй. 39 | // Инициализируй переменную с коллекцией чисел "evenList" 40 | // и добавь в неё только чётные числа в диапазоне от 0 до 50, включая 0. 41 | val evenList = mutableListOf() 42 | for (i in 0..50 step 2) { 43 | evenList.add(i) 44 | } 45 | println("\nEven numbers: $evenList") 46 | 47 | 48 | 49 | // Не исправляй! Дано: 50 | val weatherMap = mutableMapOf( 51 | "Moscow" to 2, 52 | "St. Petersburg" to -1, 53 | "Minsk" to 4 54 | ) 55 | 56 | 57 | 58 | /* Бонусные задания */ 59 | 60 | // TODO 3. В погодную карту "weatherMap" добавь погоду в "Kiev" и в "Tel-Aviv". 61 | weatherMap["Kiev"] = 6 62 | weatherMap["Tel-Aviv"] = 20 63 | 64 | // TODO 4. Отфильтруй и выведи в консоль города с погодой выше +0С. 65 | // Вызывай операторы один за другим, в виде "цепи" (chaining operators). 66 | weatherMap.filter { 67 | it.value > 0 68 | }.forEach { 69 | println("City ${it.key} has temperature of ${it.value}") 70 | } 71 | } 72 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop8.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // workshop #8 - const, companion object, extension func 4 | fun main(){ 5 | val list = mutableListOf("1", 3, 4, "Patrick", 3.4, "123-59") 6 | 7 | val p = Person("45-45-45") 8 | 9 | println("list:$list, code:${p.code}") 10 | val changedList = list.replacePlacesWithThePhoneCode(p, 4) 11 | println("changedList:$changedList") 12 | } 13 | 14 | 15 | class Person(phoneCode: String) { 16 | val code = if (phoneCode.length > maxLengthDone) phoneCode.subSequence(0, maxLengthDone) else phoneCode 17 | 18 | companion object { 19 | private const val maxLengthDone = 12 20 | } 21 | } 22 | 23 | fun List.replacePlacesWithThePhoneCode(person: Person, placeNum: Int = 3): List { 24 | return this.mapIndexed { index, any -> 25 | if (index % placeNum == 0) { 26 | person.code 27 | 28 | } else { 29 | any 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/main/kotlin/day_1_kotlin/langrus/solutions/KotlinWorkshop9.kt: -------------------------------------------------------------------------------- 1 | package day_1_kotlin.langrus.solutions 2 | 3 | // workshop #9 - generics 4 | 5 | fun main() { 6 | val p = ProgrammerDone() 7 | 8 | p.learn(Kotlin("basics")) 9 | 10 | p.learn(Kotlin("generics")) 11 | p.learn(Kotlin("coroutines")) 12 | 13 | // should be equal to 3 14 | println(p.howManyConceptsDoIKnow()) 15 | 16 | //should be Kotlin(element=coroutines) 17 | println(p.lastConcept()) 18 | 19 | p.forget(Kotlin("generics")) 20 | // should be equal to 3 21 | println(p.howManyConceptsDoIKnow()) 22 | } 23 | 24 | 25 | interface Language{ 26 | val element: String 27 | } 28 | 29 | data class JavaLanguage(override val element: String) : Language 30 | data class Kotlin(override val element: String): Language 31 | data class Swift(override val element: String): Language 32 | data class C_Sharp(override val element: String): Language 33 | 34 | 35 | class ProgrammerDone() { 36 | 37 | private val concepts = mutableListOf() 38 | 39 | fun howManyConceptsDoIKnow(): Int = concepts.size 40 | 41 | fun learn(concept: T) { 42 | concepts.add(concept) 43 | } 44 | 45 | fun forget(concept: T) { 46 | concepts.remove(concept) 47 | } 48 | 49 | fun lastConcept(): T = concepts.last() 50 | } --------------------------------------------------------------------------------