Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
20f48ec
Lessons for module 5
kajigor Apr 1, 2024
14607e3
Example code clean up
kajigor Apr 2, 2024
9a082ab
Module 5 finished
kajigor Apr 16, 2024
3151ef3
Update task.md
stephen-hero May 6, 2024
62615db
Update task.md
stephen-hero May 7, 2024
8e40b40
Update task.md
stephen-hero May 7, 2024
9563f2a
Update task.md
stephen-hero May 7, 2024
62888a7
Update task.md
stephen-hero May 7, 2024
499ebf5
Update task.md
stephen-hero May 13, 2024
e4cc0de
Update task.md
stephen-hero May 13, 2024
d41b239
Update task.md
stephen-hero May 13, 2024
79ae107
Update task.md
stephen-hero May 13, 2024
b4a0c66
Update task.md
stephen-hero May 13, 2024
31d0ecf
Update task.md
stephen-hero May 14, 2024
d33f348
Update task.md
stephen-hero May 14, 2024
4e1a1b1
Update task.md
stephen-hero May 14, 2024
baaaaa0
Update task.md
stephen-hero May 14, 2024
a1b355a
Update task.md
stephen-hero May 14, 2024
22f8e78
Update task.md
stephen-hero May 15, 2024
b8c3469
Update task.md
stephen-hero May 15, 2024
21b095a
Update task.md
stephen-hero May 15, 2024
6a08242
Update task.md
stephen-hero May 15, 2024
bf811d2
Update task.md
stephen-hero May 16, 2024
97c6032
Update task.md
stephen-hero May 16, 2024
17abccf
Update task.md
stephen-hero May 16, 2024
4e05669
Update task.md
stephen-hero May 16, 2024
fb2ca0a
Update task.md
stephen-hero May 16, 2024
a4e1bdc
Update task.md
stephen-hero May 17, 2024
aed7f57
Update task.md
stephen-hero May 17, 2024
482cf52
Update task.md
stephen-hero May 17, 2024
89c86eb
Update task.md
stephen-hero May 17, 2024
7d97044
Update task.md
stephen-hero May 17, 2024
e31335a
Update task.md
stephen-hero May 20, 2024
82a5860
Update task.md
stephen-hero May 20, 2024
f10ac68
Update task.md
stephen-hero May 20, 2024
6bc3271
Update task.md
stephen-hero May 20, 2024
9761989
Update task.md
stephen-hero May 20, 2024
a85570f
Update task.md
stephen-hero May 20, 2024
b9f3683
Update README.md
stephen-hero May 20, 2024
e038d3b
Merge pull request #44 from jetbrains-academy/stephen-hero-patch-37
kajigor May 24, 2024
a3258c7
Monads theory
kajigor May 28, 2024
733b53b
Monads module done
kajigor May 29, 2024
cd6e3e7
Merge remote-tracking branch 'origin/module-5' into module-5
kajigor May 29, 2024
29c7231
Lessons titles removed.
kajigor May 30, 2024
f3ec3ae
`unit` methods purged
kajigor May 30, 2024
be12deb
Update task.md
stephen-hero Jun 6, 2024
da06e64
Update task.md
stephen-hero Jun 7, 2024
890973f
Update task.md
stephen-hero Jun 7, 2024
799c813
Update task.md
stephen-hero Jun 10, 2024
5402ed3
Update task.md
stephen-hero Jun 10, 2024
cd0df9e
Update task.md
stephen-hero Jun 10, 2024
709c442
Update task.md
stephen-hero Jun 10, 2024
5f0240d
Update task.md
stephen-hero Jun 10, 2024
4230249
Update task.md
stephen-hero Jun 10, 2024
3d4e200
Update task.md
stephen-hero Jun 10, 2024
518cad0
Update task.md
stephen-hero Jun 10, 2024
535cbd6
Update task.md
stephen-hero Jun 10, 2024
c6642a4
Update task.md
stephen-hero Jun 10, 2024
ece6d1d
Update task.md
stephen-hero Jun 10, 2024
fcb654a
Update task.md
stephen-hero Jun 11, 2024
ffa08aa
Update task.md
stephen-hero Jun 11, 2024
3a3f869
Update task.md
stephen-hero Jun 11, 2024
1ecd79b
Update task.md
stephen-hero Jun 11, 2024
5f16362
Update task.md
stephen-hero Jun 11, 2024
8ab7bcc
Update task.md
stephen-hero Jun 11, 2024
de04b4e
Update task.md
stephen-hero Jun 11, 2024
b1a2a52
Update task.md
stephen-hero Jun 11, 2024
4555fa8
Merge pull request #45 from jetbrains-academy/stephen-hero-patch-38
kajigor Jun 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Early Returns/Baby Steps/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
scalaSource in Compile := baseDirectory.value / "src"
scalaSource in Test := baseDirectory.value / "test"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15"
scalaVersion := "3.2.0"
13 changes: 13 additions & 0 deletions Early Returns/Baby Steps/src/Breed.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
enum Breed:
case Siamese
case Persian
case MaineCoon
case Ragdoll
case Bengal
case Abyssinian
case Birman
case OrientalShorthair
case Sphynx
case DevonRex
case ScottishFold
case Metis
5 changes: 5 additions & 0 deletions Early Returns/Baby Steps/src/Cat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
case class Cat(name: String,
breed: Breed,
primaryColor: Color,
pattern: Pattern,
furCharacteristics: Set[FurCharacteristic])
11 changes: 11 additions & 0 deletions Early Returns/Baby Steps/src/Color.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
enum Color:
case Lavender
case White
case Cream
case Fawn
case Cinnamon
case Chocolate
case Orange
case Lilac
case Blue
case Black
92 changes: 92 additions & 0 deletions Early Returns/Baby Steps/src/Database.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import Breed._
import Color._
import FurCharacteristic._
import Pattern._
import TabbySubtype._
import ShadingSubtype._
import BicolorSubtype._
import TricolorSubtype._

object Database:
type CatId = Int

/**
* @param id a unique cat identifier
* @param name a cat's name
* @param adopted a flag that is true if the cat has been adopted
*/
case class CatAdoptionStatus(id: CatId, name: String, adopted: Boolean)

val identifiers: Seq[CatId] = 1 to 30

/**
* This database "table" tracks whether a cat has already been adopted.
*/
val adoptionStatusDatabase: Seq[CatAdoptionStatus] = Seq(
CatAdoptionStatus(1, "Luna", true),
CatAdoptionStatus(2, "Max", false),
CatAdoptionStatus(3, "Charlie", true),
CatAdoptionStatus(4, "Daisy", false),
CatAdoptionStatus(5, "Simba", true),
CatAdoptionStatus(6, "Oliver", false),
CatAdoptionStatus(7, "Molly", true),
CatAdoptionStatus(8, "Lucy", true),
CatAdoptionStatus(9, "Buddy", false),
CatAdoptionStatus(10, "Rocky", true),
CatAdoptionStatus(11, "Jack", false),
CatAdoptionStatus(12, "Sadie", true),
CatAdoptionStatus(13, "Ginger", false),
CatAdoptionStatus(14, "Leo", true),
CatAdoptionStatus(15, "Misty", false),
CatAdoptionStatus(16, "Rex", true),
CatAdoptionStatus(17, "Bella", true),
CatAdoptionStatus(18, "Tiger", true),
CatAdoptionStatus(19, "Zara", false),
CatAdoptionStatus(20, "Sophie", true),
CatAdoptionStatus(21, "Ollie", false),
CatAdoptionStatus(22, "Pixie", true),
CatAdoptionStatus(23, "Fuzz", false),
CatAdoptionStatus(24, "Scotty", true),
CatAdoptionStatus(25, "Mixie", true),
CatAdoptionStatus(26, "Cleo", true),
CatAdoptionStatus(27, "Milo", false),
CatAdoptionStatus(28, "Nala", true),
CatAdoptionStatus(29, "Loki", false),
CatAdoptionStatus(30, "Shadow", true)
)

/**
* This database "table" contains the basic information about each cat.
*/
val catDatabase: Seq[Cat] = Seq(
Cat("Luna", Siamese, Blue, Pattern.SolidColor, Set(Fluffy)), // Invalid
Cat("Max", Persian, Black, Pattern.Tabby(Mackerel), Set(ShortHaired)), // Invalid
Cat("Charlie", MaineCoon, Orange, Pattern.SolidColor, Set(SleekHaired)), // Invalid
Cat("Daisy", Ragdoll, Cream, Pattern.Bicolor(Van), Set(ShortHaired)), // Invalid
Cat("Simba", Bengal, Blue, Pattern.SolidColor, Set(LongHaired)), // Invalid
Cat("Oliver", ScottishFold, Cinnamon, Pattern.Spots, Set(WireHaired)), // Invalid
Cat("Molly", Persian, White, Pattern.Shading(Shaded), Set(Fluffy, DoubleCoated)), // Valid
Cat("Lucy", Metis, Blue, Pattern.Pointed, Set(SleekHaired, Fluffy)), // Metis can be anything
Cat("Buddy", Siamese, Cream, Pattern.Tabby(Mackerel), Set(LongHaired)), // Invalid
Cat("Rocky", MaineCoon, Black, Pattern.Tricolor(Tortie), Set(ShortHaired)), // Invalid
Cat("Jack", Bengal, Chocolate, Pattern.Tabby(Spotted), Set(ShortHaired, Plush)), // Invalid
Cat("Sadie", Birman, White, Pattern.Bicolor(Van), Set(LongHaired, Fluffy)), // Valid
Cat("Ginger", Abyssinian, Orange, Pattern.Tabby(Ticked), Set(ShortHaired, SleekHaired)), // Valid
Cat("Leo", Siamese, Cream, Pattern.SolidColor, Set(ShortHaired, SleekHaired)), // Valid
Cat("Misty", Persian, White, Pattern.SolidColor, Set(LongHaired, Fluffy)), // Valid
Cat("Rex", MaineCoon, Black, Pattern.Tabby(Classic), Set(LongHaired, DoubleCoated)), // Valid
Cat("Bella", Ragdoll, Blue, Pattern.Pointed, Set(Fluffy)), // Valid
Cat("Tiger", Bengal, Orange, Pattern.Spots, Set(ShortHaired)), // Valid
Cat("Zara", Abyssinian, Cinnamon, Pattern.Tabby(Ticked), Set(ShortHaired)), // Valid
Cat("Sophie", Birman, Lilac, Pattern.Pointed, Set(LongHaired, Fluffy)), // Valid
Cat("Ollie", OrientalShorthair, Lavender, Pattern.SolidColor, Set(SleekHaired)), // Valid
Cat("Pixie", Sphynx, Lilac, Pattern.SolidColor, Set(WireHaired)), // Valid
Cat("Fuzz", DevonRex, Cream, Pattern.SolidColor, Set(ShortHaired, WireHaired)), // Valid
Cat("Scotty", ScottishFold, White, Pattern.Bicolor(Tuxedo), Set(ShortHaired)), // Valid
Cat("Mixie", Metis, Chocolate, Pattern.Tricolor(Calico), Set(DoubleCoated)), // Metis can be anything
Cat("Cleo", Abyssinian, Fawn, Pattern.Tricolor(Tortie), Set(Fluffy)), // Invalid
Cat("Milo", Birman, Lavender, Pattern.SolidColor, Set(SleekHaired)), // Invalid
Cat("Nala", OrientalShorthair, Black, Pattern.Shading(Chinchilla), Set(Fluffy)), // Invalid
Cat("Loki", Sphynx, White, Pattern.Shading(Shaded), Set(LongHaired)), // Invalid
Cat("Shadow", DevonRex, Lilac, Pattern.SolidColor, Set(LongHaired)) // Invalid
)
80 changes: 80 additions & 0 deletions Early Returns/Baby Steps/src/EarlyReturns.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
object EarlyReturns:
private type UserId = Int
private type Email = String

case class UserData(id: UserId, name: String, email: Email)

/**
* Pretend database of user data.
*/
private val database = Seq(
UserData(1, "Ayaan Sharma", "ayaan@gmail.com"),
UserData(2, "Lei Zhang", "lei_zhang@yahoo.cn"),
UserData(3, "Fatima Al-Fassi", "fatima.alfassi@outlook.sa"),
UserData(4, "Ana Sofia Ruiz", "ana_sofia@icloud.es"),
UserData(5, "Oluwaseun Adeyemi", "oluwaseun@hotmail.ng"),
UserData(6, "Maria Ivanova", "maria.ivanova@aol.ru"),
UserData(7, "Yuto Nakamura", "yuto.nakamura@mail.jp"),
UserData(8, "Chiara Rossi", "chiara@live.it"),
UserData(9, "Lucas Müller", "lucas@protonmail.de"),
UserData(10, "Sara Al-Bahrani", "sara.albahrani@gmail.com"),
UserData(11, "Min-Jun Kim", "minjun.kim@yahoo.kr")
)

private val identifiers = 1 to 11

/**
* This is our pretend "complex conversion" method.
* We assume that it is costly to retrieve user data, so we want to avoid
* calling it unless it's absolutely necessary.
*
* This version of the method assumes that the user data always exists for a given user id.
*
* @param userId the identifier of a user for whom we want to retrieve the data
* @return the user data
*/
def complexConversion(userId: UserId): UserData =
database.find(_.id == userId).get

/**
* Similar to `complexConversion`, the validation of user data is costly
* and we shouldn't do it too often.
*
* @param user user data
* @return true if the user data is valid, false otherwise
*/
def complexValidation(user: UserData): Boolean =
!user.email.contains(' ') && user.email.count(_ == '@') == 1

/**
* Imperative approach that uses un-idiomatic `return`.
*
* @param userIds the sequence of all user identifiers
* @return `Some` of the first valid user data or `None` if no valid user data is found
*/
def findFirstValidUser1(userIds: Seq[UserId]): Option[UserData] =
for userId <- userIds do
val userData = complexConversion(userId)
if (complexValidation(userData)) return Some(userData)
None

/**
* Naive functional approach: calls `complexConversion`` twice on the selected ID.
* @param userIds the sequence of all user identifiers
* @return `Some` of the first valid user data or `None` if no valid user data is found
*/
def findFirstValidUser2(userIds: Seq[UserId]): Option[UserData] =
userIds
.find(userId => complexValidation(complexConversion(userId)))
.map(complexConversion)

/**
* A more concise implementation which uses `collectFirst`.
*
* @param userIds the sequence of all user identifiers
* @return `Some` of the first valid user data or `None` if no valid user data is found
*/
def findFirstValidUser3(userIds: Seq[UserId]): Option[UserData] =
userIds.collectFirst {
case userId if complexValidation(complexConversion(userId)) => complexConversion(userId)
}
8 changes: 8 additions & 0 deletions Early Returns/Baby Steps/src/FurCharacteristic.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
enum FurCharacteristic:
case LongHaired
case ShortHaired
case Fluffy
case Plush
case SleekHaired
case WireHaired
case DoubleCoated
28 changes: 28 additions & 0 deletions Early Returns/Baby Steps/src/Pattern.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
enum TabbySubtype:
case Classic
case Ticked
case Mackerel
case Spotted
case Patched

enum ShadingSubtype:
case Chinchilla
case Shaded
case Smoke

enum BicolorSubtype:
case Tuxedo
case Van

enum TricolorSubtype:
case Calico
case Tortie

enum Pattern:
case Tabby(val subType: TabbySubtype)
case Pointed
case Shading(val subType: ShadingSubtype)
case SolidColor
case Bicolor(val subType: BicolorSubtype)
case Tricolor(val subType: TricolorSubtype)
case Spots
77 changes: 77 additions & 0 deletions Early Returns/Baby Steps/src/Task.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import Database._
import Breed._
import FurCharacteristic._

object Task:
/**
* Implement the conversion method: find a cat's name by its ID in the adoptionStatusDatabase,
* and then fetch the cat data from the catsDatabase.
*
* @param catId the identifier of a cat for whom we want to retrieve the data
* @return the cat data
*/
def catConversion(catId: CatId): Cat =
print(s"Cat conversion: $catId\n")
val status = adoptionStatusDatabase.find(_.id == catId).get
catDatabase.find(_.name == status.name).get

private val breedCharacteristics: Map[Breed, Set[FurCharacteristic]] = Map(
Siamese -> Set(ShortHaired, SleekHaired),
Persian -> Set(LongHaired, Fluffy, DoubleCoated),
MaineCoon -> Set(LongHaired, Fluffy, DoubleCoated),
Ragdoll -> Set(LongHaired, Fluffy, DoubleCoated),
Bengal -> Set(ShortHaired),
Abyssinian -> Set(ShortHaired, SleekHaired),
Birman -> Set(LongHaired, Fluffy, DoubleCoated),
OrientalShorthair -> Set(ShortHaired, SleekHaired),
Sphynx -> Set(WireHaired, Plush),
DevonRex -> Set(ShortHaired, Plush, WireHaired),
ScottishFold -> Set(ShortHaired, LongHaired, DoubleCoated),
Metis -> Set(LongHaired, ShortHaired, Fluffy, Plush, SleekHaired, WireHaired, DoubleCoated) // Assuming Metis can have any characteristics
)

/**
* Implement the validation: the characteristics of the cat's fur should feed their breed.
*
* @param cat cat data
* @return true if the user data is valid, false otherwise
*/
def furCharacteristicValidation(cat: Cat): Boolean =
print(s"Validation of fur characteristics: ${cat.name}\n")
val validCharacteristics = breedCharacteristics(cat.breed)
cat.furCharacteristics.forall(validCharacteristics.contains)


/**
* Imperative approach that uses un-idiomatic `return`.
*
* @param catIds the sequence of all cat identifiers
* @return `Some` of the first valid user data or `None` if no valid user data is found
*/
def imperativeFindFirstValidCat(catIds: Seq[CatId]): Option[Cat] =
for catId <- catIds do
val catData = catConversion(catId)
if (furCharacteristicValidation(catData)) return Some(catData)
None

/**
* Implement the naive functional approach.
*
* @param catIds the sequence of all cat identifiers
* @return `Some` of the first valid user data or `None` if no valid cat data is found
*/
def functionalFindFirstValidCat(catIds: Seq[CatId]): Option[Cat] =
catIds
.find(catId => furCharacteristicValidation(catConversion(catId)))
.map(catConversion)

/**
* Use `collectFirst` here.
*
* @param catIds the sequence of all cat identifiers
* @return `Some` of the first valid cat data or `None` if no valid cat data is found
*/
def collectFirstFindFirstValidCat(userIds: Seq[CatId]): Option[Cat] =
userIds.collectFirst {
case catId if furCharacteristicValidation(catConversion(catId)) => catConversion(catId)
}
38 changes: 38 additions & 0 deletions Early Returns/Baby Steps/task-info.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
type: edu
files:
- name: src/Task.scala
visible: true
placeholders:
- offset: 434
length: 107
placeholder_text: /* TODO */
- offset: 1642
length: 123
placeholder_text: /* TODO */
- offset: 2061
length: 141
placeholder_text: /* TODO */
- offset: 2484
length: 104
placeholder_text: /* TODO */
- offset: 2856
length: 122
placeholder_text: /* TODO */
- name: test/TestSpec.scala
visible: false
- name: build.sbt
visible: false
- name: src/EarlyReturns.scala
visible: true
- name: src/Cat.scala
visible: true
- name: src/FurCharacteristic.scala
visible: true
- name: src/Pattern.scala
visible: true
- name: src/Color.scala
visible: true
- name: src/Breed.scala
visible: true
- name: src/Database.scala
visible: true
Loading