diff --git a/JavaOOP.iml b/JavaOOP.iml new file mode 100644 index 0000000..f392c3c --- /dev/null +++ b/JavaOOP.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/lab_1/main.java b/lab_1/main.java new file mode 100644 index 0000000..0bd9bb2 --- /dev/null +++ b/lab_1/main.java @@ -0,0 +1,33 @@ + package lab_1; + +import java.util.Scanner; + +public class main { + + public static int protectedInput(String variableToRead, Scanner input) { + do { + try { + System.out.printf("Enter %s: ", variableToRead); + return input.nextInt(); + } catch (Exception e) { + System.out.printf("%s must be an integer.\n", variableToRead.toUpperCase()); + input.nextLine(); + } + } while (true); + } + + public static void main(String[] args) { + Scanner input = new Scanner(System.in); + + final int n = protectedInput("n", input); + final int m = protectedInput("m", input); + final int a = protectedInput("a", input); + final int b = protectedInput("b", input); + + input.close(); + + final float s = ((float) (b + m) / 2) * (m - b + 1) * (n - a + 1); + + System.out.println("S = " + s); + } +} diff --git a/lab_1/main.kt b/lab_1/main.kt new file mode 100644 index 0000000..83a0cd7 --- /dev/null +++ b/lab_1/main.kt @@ -0,0 +1,23 @@ +package lab_1 + +fun protectedInput(variableName: String): Int { + do { + try { + print("Enter $variableName: ") + return readln().toInt() + } catch (e: Exception) { + println("${variableName.uppercase()} must be an integer!") + } + } while (true) +} + +fun main() { + val n: Int = protectedInput("n") + val m: Int = protectedInput("m") + val a: Int = protectedInput("a") + val b: Int = protectedInput("b") + + val s: Float = (b + m).toFloat() / 2 * (m - b + 1) * (n - a + 1) + + println("S = $s") +} \ No newline at end of file diff --git a/lab_2/main.java b/lab_2/main.java new file mode 100644 index 0000000..8173450 --- /dev/null +++ b/lab_2/main.java @@ -0,0 +1,109 @@ +package lab_2; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.util.Scanner; + +public class main { + + public static short protectedInput(String inputPrompt, String errorMessage, Scanner input) { + short read_variable; + + do { + try { + System.out.println(); + System.out.print(inputPrompt); + + read_variable = input.nextShort(); + break; + } catch (Exception e) { + System.out.println(errorMessage); + input.nextLine(); + } + } while (true); + + return read_variable; + } + + @NotNull + public static String format(int number) { + int width = String.valueOf(number).length() + 1; + + return "|%" + width + "d "; + } + + @Contract(pure = true) + public static double average(@NotNull short[] row) { + short sum = 0; + + for (short element : row) { + sum += element; + } + + return (double) sum / row.length; + } + + public static void main(String[] args) { + short rows, columns; + + Scanner input = new Scanner(System.in); + + final short a = protectedInput("Input a constant to multiply a matrix by: ", + "A constant must be a short-data type integer, try again.", input); + + System.out.println(); + System.out.println("Input size of the matrix."); + + do { + rows = protectedInput("Rows: ", + "A number of rows must be a short-data type integer, try again.", input); + } while (rows <= 0); + + do { + columns = protectedInput("Columns: ", + "A number of columns must be a short-data type integer, try again.", input); + } while (columns <= 0); + + input.close(); + + short[][] matrix_B = new short[rows][columns]; + + System.out.println(); + System.out.println("Matrix B:"); + + String format = format(rows * columns); + + for (short i = 0; i < rows; i++) { + for (short j = 0; j < columns; j++) { + matrix_B[i][j] = (short) ((i + 1) * (j + 1)); + + System.out.printf(format, matrix_B[i][j]); + } + + System.out.println("|"); + } + + System.out.println(); + System.out.println("Matrix a×B:"); + + format = format(rows * columns * a); + + for (short i = 0; i < matrix_B.length; i++) { + for (short j = 0; j < matrix_B[i].length; j++) { + matrix_B[i][j] *= (a); + + System.out.printf(format, matrix_B[i][j]); + } + + System.out.println("|"); + } + + System.out.println(); + System.out.println("Averages of each row:"); + + for (short[] row : matrix_B) { + System.out.println(average(row)); + } + } +} diff --git a/lab_3/main.java b/lab_3/main.java new file mode 100644 index 0000000..82ee446 --- /dev/null +++ b/lab_3/main.java @@ -0,0 +1,57 @@ +package lab_3; + +public class main { + static int maxStrLength; + static String result; + + public static void cSubUtil(StringBuilder stringbuilder, int leftBoundary, int rightBoundary) { + String string = stringbuilder.toString().toLowerCase().replaceAll("[^a-z]",""); + // check if the indices lie in the range of string + // and also if it is palindrome + while (leftBoundary >= 0 && rightBoundary < string.length() && string.toLowerCase().charAt(leftBoundary) == string.toLowerCase().charAt(rightBoundary)) { + // expand the boundary + leftBoundary--; + rightBoundary++; + } + // if it's length is greater than maxStrLength update + // maxLength and result + if (rightBoundary - leftBoundary - 1 >= maxStrLength) { + result = string.substring(leftBoundary + 1, rightBoundary); + maxStrLength = rightBoundary - leftBoundary - 1; + } + } + + public static int longestPalSubstr(StringBuilder string) + { + result = ""; + maxStrLength = 1; + // for every index in the string check palindromes + // starting from that index + for (int i = 0; i < string.length(); i++) { + // check for odd length palindromes + cSubUtil(string, i, i); + // check for even length palindromes + cSubUtil(string, i, i + 1); + } + System.out.println("Longest palindrome substring is: " + compareStrings(string)); + return compareStrings(string).length(); + } + + public static String compareStrings(StringBuilder builder) { + for (int leftBoundary = 0; leftBoundary <= builder.length(); leftBoundary++) { + for (int rightBoundary = builder.length(); rightBoundary >= leftBoundary; rightBoundary--) { + if (result.equals(builder.substring(leftBoundary, rightBoundary).toLowerCase().replaceAll("[^a-z]",""))) { + return builder.substring(leftBoundary, rightBoundary); + } + } + } + return ""; + } + + public static void main(String[] args) { + StringBuilder stringToDetect = new StringBuilder("Eva, can I see bees in a cave?"); + + System.out.println("Initial string: " + stringToDetect); + System.out.println("Length is: " + longestPalSubstr(stringToDetect)); + } +} diff --git a/lab_4/Furniture.kt b/lab_4/Furniture.kt new file mode 100644 index 0000000..e44d555 --- /dev/null +++ b/lab_4/Furniture.kt @@ -0,0 +1,15 @@ +package lab_4 + +class Furniture(val name: String, val material: String, val price: Int, private val length: Int, private val width: Int, private val height: Int) { + fun print(nameWidth: Int, materialWidth: Int, priceWidth: Int){ + val printString = StringBuilder() + printString +// .append("Furniture stats: {") + .append("Name: ${this.name.padEnd(nameWidth)} ") + .append("Material: ${this.material.padEnd(materialWidth)} ") + .append("Price: ${(this.price.toString() + " cu").padEnd(priceWidth + 3)} ") + .append("Size: ${this.length}×${this.width}×${this.height}") + + println(printString) + } +} \ No newline at end of file diff --git a/lab_4/main.kt b/lab_4/main.kt new file mode 100644 index 0000000..270ad56 --- /dev/null +++ b/lab_4/main.kt @@ -0,0 +1,24 @@ +package lab_4 + +fun main() { + val furnitureArray = listOf( + Furniture("Chair", "Wood", 10, 5, 5, 10), + Furniture("Counter-top", "Marble", 1_000, 10, 5, 1), + Furniture("Dinner table", "Glass", 500, 15, 10, 1), + Furniture("Office table", "Wood", 200, 10, 7, 1), + Furniture("Refrigerator", "Stainless steel", 20_000, 8, 4, 10) + ) + + val maxNameWidth = furnitureArray.maxBy {it.name.length}.name.length + val maxMaterialWidth = furnitureArray.maxBy { it.material.length }.material.length + val maxPriceWidth = furnitureArray.maxBy { it.price }.price.toString().length + + println("\nUnsorted array:") + furnitureArray.forEach { it.print(maxNameWidth, maxMaterialWidth, maxPriceWidth) } + + println("\nSorted alphabetically by name:") + furnitureArray.sortedBy { it.name }.forEach { it.print(maxNameWidth, maxMaterialWidth, maxPriceWidth) } + + println("\nSorted alphabetically by material:") + furnitureArray.sortedBy { it.material }.forEach { it.print(maxNameWidth, maxMaterialWidth, maxPriceWidth) } +} \ No newline at end of file diff --git a/lab_5/Letter.kt b/lab_5/Letter.kt new file mode 100644 index 0000000..c95685e --- /dev/null +++ b/lab_5/Letter.kt @@ -0,0 +1,23 @@ +package lab_5 + +/** + * A class representing a single letter in a word. + * + * @property character a character value of a Letter. + */ +class Letter(private val character: Char) { + override fun toString(): String { + return this.character.toString() + } + + /** + * Indicates whether the two objects of class Letter are "equal". + * + * @param letter a letter to compare. + * @param ignoreCase if set to "true" will ignore the case of Letters compared. + * @return "true" if letters are equal and "false" if they aren't. + */ + fun letterEquals(letter: Letter, ignoreCase: Boolean): Boolean { + return this.character.toString().equals(letter.toString(), ignoreCase) + } +} \ No newline at end of file diff --git a/lab_5/Punctuation.kt b/lab_5/Punctuation.kt new file mode 100644 index 0000000..7ada537 --- /dev/null +++ b/lab_5/Punctuation.kt @@ -0,0 +1,19 @@ +package lab_5 + +/** + * A class representing a punctuation mark following a word or a sentence. + * + * @property punctuationMark a [String] value of a punctuation mark. + */ +class Punctuation(var punctuationMark: String) { + + init { + if (!"\\p{Punct}".toRegex().containsMatchIn(punctuationMark)) { + this.punctuationMark = "" + } + } + + override fun toString(): String { + return punctuationMark + } +} \ No newline at end of file diff --git a/lab_5/Sentence.kt b/lab_5/Sentence.kt new file mode 100644 index 0000000..e5732e0 --- /dev/null +++ b/lab_5/Sentence.kt @@ -0,0 +1,46 @@ +package lab_5 + +import lab_5.Letter + +/** + * A class representing a single sentence is a text. + * + * @property sentenceArray a [Pair] of [Array]s of [Word] and [Punctuation] objects that make up a sentence. + * + * @constructor a primary constructor accepts a [Pair] of [Array]s of [Word] and [Punctuation] objects, a secondary one accepts a string representing the entire sentence. + */ +class Sentence(var sentenceArray: Pair, Array>) { + + constructor( + sentenceString: String + ) : this( + Pair( + sentenceString.split("[\\p{Punct}\\s]+".toRegex()) + .filter { it.isNotEmpty() } + .map { word -> Word(word) } + .toTypedArray(), + sentenceString.split(" ") + .map { word -> Punctuation(word.last().toString()) } + .toTypedArray() + ) + ) + + /** + * Returns an array of all [Letter] objects in a sentence. + */ + fun getAllLetters(): Array { + var allLetters = arrayOf() + this.sentenceArray.first.forEach { allLetters += it.letters } + + return allLetters + } + + override fun toString(): String { + val sentence = mutableListOf() + this.sentenceArray.first.indices.forEach { + sentence += this.sentenceArray.first[it].toString() + this.sentenceArray.second[it].toString() + } + + return sentence.joinToString(" ") + } +} \ No newline at end of file diff --git a/lab_5/Text.kt b/lab_5/Text.kt new file mode 100644 index 0000000..09613c1 --- /dev/null +++ b/lab_5/Text.kt @@ -0,0 +1,96 @@ +package lab_5 + +/** + * A class representing the entire text. + * + * @property textArray a [Pair] of [Array]s of [Sentence] and [Punctuation] objects that make up a text. + * + * @constructor a primary constructor accepts a [Pair] of [Array]s of [Sentence] and [Punctuation] objects, a secondary one accepts a string representing the entire text. + */ +class Text(private var textArray: Pair, Array>) { + + constructor( + textString: String + ) : this( + Pair( + textString.split("[.!?] ?".toRegex()) + .filter { it.isNotEmpty() } + .map { sentence -> Sentence(sentence) } + .toTypedArray(), + textString.split("(?<=[.!?]) ?".toRegex()) + .filter { it.isNotEmpty() } + .map { sentence -> Punctuation(sentence.last().toString()) } + .toTypedArray() + ) + ) + + /** + * Returns an array of all [Letter] objects in a sentence. + */ + private fun getAllLetters(): Array { + var allLetters = arrayOf() + this.textArray.first.forEach { allLetters += it.getAllLetters() } + return allLetters + } + + /** + * Searches for the longest palindromic substring in a given text. + * + * @return the longest palindromic substring found. + */ + fun palindromeSearch(): String { + var result = " " + + val letters = this.getAllLetters() + + for (leftBoundary in letters.indices) { + for (rightBoundary in letters.lastIndex downTo leftBoundary + 1) { + val substringToC = letters.sliceArray(leftBoundary..rightBoundary) + + val letterEquals = substringToC.first().letterEquals(substringToC.last(), true) + val isAPalindrome = this.checkReverse(substringToC) + val isLargerThanPrevious = substringToC.size > result.length + + if (letterEquals && isAPalindrome && isLargerThanPrevious) { + result = substringToC.joinToString("") + } + } + } + + return result + } + + /** + * Checks if a given substring is a palindrome. + * + * Is not case-sensitive. + * + * @param substring an [Array] of [Letter] objects representing a substring. + * + * @return "true" is a substring given is a palindrome, "false" if it isn't. + */ + private fun checkReverse(substring: Array): Boolean { + var leftBoundary = 0 + var rightBoundary = substring.lastIndex + var result = false + val correction = substring.size % 2 + + while (leftBoundary < substring.size / 2 && rightBoundary >= substring.size / 2 + correction) { + leftBoundary++ + rightBoundary-- + result = substring[leftBoundary].letterEquals(substring[rightBoundary], true) + } + + return result + } + + + override fun toString(): String { + var text = arrayOf() + this.textArray.first.indices.forEach { + text += this.textArray.first[it].toString() + this.textArray.second[it].toString() + } + + return text.joinToString(" ") + } +} \ No newline at end of file diff --git a/lab_5/Word.kt b/lab_5/Word.kt new file mode 100644 index 0000000..e138c67 --- /dev/null +++ b/lab_5/Word.kt @@ -0,0 +1,24 @@ +package lab_5 + +import lab_5.Letter + +/** + * A class representing a single word is a sentence. + * + * @property letters an array of [Letter] objects that make up a word. + * + * @constructor a primary constructor accepts an array of [Letter] objects, a secondary one accepts a string representing the entire word. + */ +class Word(var letters: Array) { + + override fun toString(): String { + val wordString = StringBuilder() + this.letters.forEach { wordString.append(it) } + + return wordString.toString() + } + + constructor( + word: String + ) : this((word.toCharArray().map { letter -> Letter(letter) }).toTypedArray()) +} \ No newline at end of file diff --git a/lab_5/main.kt b/lab_5/main.kt new file mode 100644 index 0000000..cff6051 --- /dev/null +++ b/lab_5/main.kt @@ -0,0 +1,8 @@ +package lab_5 + +fun main() { + val textString = "Я Анна марія! kayak taco cat" + val text = Text(textString) + println(text) + println(text.palindromeSearch()) +} \ No newline at end of file diff --git a/lab_6/Album.kt b/lab_6/Album.kt new file mode 100644 index 0000000..39bbd6f --- /dev/null +++ b/lab_6/Album.kt @@ -0,0 +1,33 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents an album by a specific artist, containing multiple tracks. + * + * @property albumName The name of the album. + * @property artist The artist or band associated with the album. + * @property tracks An [Array] of tracks included on the album. + */ +class Album(val albumName: String, val artist: String, val tracks: List) { + + /** + * Returns an array of tracks within the specified duration range. + */ + fun tracksInDurationRange(durationRange: ClosedRange): Array { + return this.tracks.filter { it.duration in durationRange }.toTypedArray() + } + + /** + * Returns the total duration of all tracks on the album. + */ + private fun totalDuration(): Duration { + var totalDuration: Duration = Duration.ZERO + this.tracks.forEach { totalDuration += it.duration } + return totalDuration + } + + override fun toString(): String { + return "${this.albumName} by ${this.artist}\nTotal duration: ${this.totalDuration()}\nTracks:\n${this.tracks.joinToString("\n")}" + } +} \ No newline at end of file diff --git a/lab_6/Dancepop.kt b/lab_6/Dancepop.kt new file mode 100644 index 0000000..e1925cc --- /dev/null +++ b/lab_6/Dancepop.kt @@ -0,0 +1,15 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents a track in the Dance-pop style. + * + * @param numberInAlbum The position of the track on the album. + * @param trackName The name of the track. + * @param feature The featured artist(s) in the track (nullable if no featured artist). + * @param duration The [Duration] of the track. + */ +class Dancepop(numberInAlbum: Int, trackName: String, feature: String?, duration: Duration): Track(numberInAlbum, trackName, feature, duration) { + override val style = "Dance-pop" +} \ No newline at end of file diff --git a/lab_6/Electropop.kt b/lab_6/Electropop.kt new file mode 100644 index 0000000..cecd918 --- /dev/null +++ b/lab_6/Electropop.kt @@ -0,0 +1,15 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents a track in the Electropop style. + * + * @param numberInAlbum The position of the track on the album. + * @param trackName The name of the track. + * @param feature The featured artist(s) in the track (nullable if no featured artist). + * @param duration The [Duration] of the track. + */ +class Electropop(numberInAlbum: Int, trackName: String, feature: String?, duration: Duration): Track(numberInAlbum, trackName, feature, duration) { + override val style = "Electropop" +} \ No newline at end of file diff --git a/lab_6/Interlude.kt b/lab_6/Interlude.kt new file mode 100644 index 0000000..321a00b --- /dev/null +++ b/lab_6/Interlude.kt @@ -0,0 +1,15 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents an interlude track. + * + * @param numberInAlbum The position of the track on the album. + * @param trackName The name of the track. + * @param feature The featured artist(s) in the track (nullable if no featured artist). + * @param duration The [Duration] of the track. + */ +class Interlude(numberInAlbum: Int, trackName: String, feature: String?, duration: Duration): Track(numberInAlbum, trackName, feature, duration) { + override val style = "Interlude" +} \ No newline at end of file diff --git a/lab_6/Synthpop.kt b/lab_6/Synthpop.kt new file mode 100644 index 0000000..ba71792 --- /dev/null +++ b/lab_6/Synthpop.kt @@ -0,0 +1,15 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents a track in the Synth-pop style. + * + * @param numberInAlbum The position of the track on the album. + * @param trackName The name of the track. + * @param feature The featured artist(s) in the track (nullable if no featured artist). + * @param duration The [Duration] of the track. + */ +class Synthpop(numberInAlbum: Int, trackName: String, feature: String?, duration: Duration): Track(numberInAlbum, trackName, feature, duration) { + override val style = "Synth-pop" +} \ No newline at end of file diff --git a/lab_6/Track.kt b/lab_6/Track.kt new file mode 100644 index 0000000..935637e --- /dev/null +++ b/lab_6/Track.kt @@ -0,0 +1,27 @@ +package lab_6 + +import kotlin.time.Duration + +/** + * Represents a track on an album. + * + * @param numberInAlbum The position of the track on the album. + * @param trackName The name of the track. + * @param feature The featured artist(s) in the track (nullable if no featured artist). + * @param duration The [Duration] of the track. + */ +open class Track(val numberInAlbum: Int, val trackName: String, val feature: String?, val duration: Duration) { + + /** + * The style or genre of the track. + */ + open val style = "" + + override fun toString(): String { + return if (this.feature == null) { + "#${this.numberInAlbum}: ${this.trackName} (${this.duration})" + } else { + "#${this.numberInAlbum}: ${this.trackName} ft. ${this.feature} (${this.duration})" + } + } +} diff --git a/lab_6/main.kt b/lab_6/main.kt new file mode 100644 index 0000000..b43dbc5 --- /dev/null +++ b/lab_6/main.kt @@ -0,0 +1,48 @@ +package lab_6 + +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds + +fun main() { + + val chromatica = Album( + "Chromatica", + "Lady Gaga", + listOf( + Interlude(1, "Chromatica I", null, 1.minutes), + Synthpop(2, "Alice", null, 2.minutes + 57.seconds), + Dancepop(3, "Stupid Love", null, 3.minutes + 13.seconds), + Dancepop(4, "Rain On Me", "Ariana Grande", 3.minutes + 2.seconds), + Synthpop(5, "Free Woman", null, 3.minutes + 11.seconds), + Electropop(6, "Fun Tonight", null, 2.minutes + 53.seconds), + Interlude(7, "Chromatica II", null, 41.seconds), + Synthpop(8, "911", null, 2.minutes + 52.seconds), + Electropop(9, "Plastic Doll", null, 3.minutes + 41.seconds), + Dancepop(10, "Sour Candy", "Blackpink", 2.minutes + 37.seconds), + Dancepop(11, "Enigma", null, 2.minutes + 59.seconds), + Synthpop(12, "Replay", null, 3.minutes + 6.seconds), + Interlude(13, "Chromatica III", null, 27.seconds), + Electropop(14, "Sine From Above", "Elton John", 4.minutes + 4.seconds), + Synthpop(15, "1000 Doves", null, 3.minutes + 35.seconds), + Dancepop(16, "Babylon", null, 2.minutes + 41.seconds) + ) + ) + + println("$chromatica\n") + + println( + "${chromatica.albumName} tracks sorted by musical style:\n${ + chromatica.tracks.sortedBy { it.style }.joinToString("\n") + }\n" + ) + + val durationRange = 1.minutes..3.minutes + 30.seconds + + println( + "${chromatica.albumName} tracks in a duration range ($durationRange):\n${ + chromatica.tracksInDurationRange(durationRange).joinToString("\n") + }" + ) +} + +