patternMinor
Pouring water problem
Viewed 0 times
problempouringwater
Problem
I just began to study Scala (coming from Python I had quite a few problems with types) and I want to know if my first code to solve a real problem is nicely done or if there is some points that need to be redone.
The problem I had to solve is for an homework but my code is already working, I just want to know if it be more Scalish:
Problem description
We have \$k\$ containers, where \$3 ≤ k ≤ 10\$. Container \$i\$ has a certain integer capacity \$c_i > 0\$ (of liters of water). Initially, container \$i\$ contains an integer amount \$a_i ≥ 0\$ of water. We are allowed to perform only one kind of operations: Take one container \$i\$, and pour its contents into a different container \$j\$. Pouring stops when either \$i\$ becomes empty, or \$j\$ becomes full (so after the operation either \$a_i = 0\$ or \$a_j = c_j\$).
Is it possible to achieve a certain target configuration, and, if so, how?
For instance, let's assume we have three containers with capacities \$10L\$, \$7L\$, and \$4L\$. Initially, the \$7L\$ and \$4L\$ container are full, while the \$10L\$ container is empty. The question is if we can achieve that the \$4L\$ container contains exactly \$2L\$ of water.
With our notation, we have \$k = 3\$, \$c_1 = 10\$, \$c_2 = 7\$, \$c_3 = 4\$, \$a_1 = 0\$, \$a_2 = 7\$, and \$a_3 = 4\$. The question is: Is it possible to reach \$a_3 = 2\$?
The answer is yes, and here is a possible sequence of moves (displayed in reverse order):
I solved the problem using BFS on a graph I'm building at every step.
```
import collection.mutable.HashSet
import collection.mutable.Queue
import collection.mutable.ArraySeq
import scala.io.Source
import java.io.File
case class Container(capacity: Int, filled: Int) {
// overload + and - methods
def +(toAdd: Int) = {
assert (filled + toAdd = 0, { println("Not enough water in container")})
new Container(capacity, filled - toSub
The problem I had to solve is for an homework but my code is already working, I just want to know if it be more Scalish:
Problem description
We have \$k\$ containers, where \$3 ≤ k ≤ 10\$. Container \$i\$ has a certain integer capacity \$c_i > 0\$ (of liters of water). Initially, container \$i\$ contains an integer amount \$a_i ≥ 0\$ of water. We are allowed to perform only one kind of operations: Take one container \$i\$, and pour its contents into a different container \$j\$. Pouring stops when either \$i\$ becomes empty, or \$j\$ becomes full (so after the operation either \$a_i = 0\$ or \$a_j = c_j\$).
Is it possible to achieve a certain target configuration, and, if so, how?
For instance, let's assume we have three containers with capacities \$10L\$, \$7L\$, and \$4L\$. Initially, the \$7L\$ and \$4L\$ container are full, while the \$10L\$ container is empty. The question is if we can achieve that the \$4L\$ container contains exactly \$2L\$ of water.
With our notation, we have \$k = 3\$, \$c_1 = 10\$, \$c_2 = 7\$, \$c_3 = 4\$, \$a_1 = 0\$, \$a_2 = 7\$, and \$a_3 = 4\$. The question is: Is it possible to reach \$a_3 = 2\$?
The answer is yes, and here is a possible sequence of moves (displayed in reverse order):
2 7 2
2 5 4
6 5 0
6 1 4
10 1 0
4 7 0
0 7 4I solved the problem using BFS on a graph I'm building at every step.
```
import collection.mutable.HashSet
import collection.mutable.Queue
import collection.mutable.ArraySeq
import scala.io.Source
import java.io.File
case class Container(capacity: Int, filled: Int) {
// overload + and - methods
def +(toAdd: Int) = {
assert (filled + toAdd = 0, { println("Not enough water in container")})
new Container(capacity, filled - toSub
Solution
It seems pretty reasonable, actually. I'm confused by the
As
That is, if used
I'm not sure
ArraySeq. Also, I'd rewrite this:if (Option(parent) != None) parent :: parent.ancesters
else List[State]()As
Option(parent).map(parent => parent :: parent.ancesters).getOrElse(List[State]())That is, if used
parent as you did. I'd make it an Option instead, and initialize it at creation.I'm not sure
Iterator would help you here, but Stream might. I just don't think it is a particular good fit for BFS, but it might just be ignorance on my part.Code Snippets
if (Option(parent) != None) parent :: parent.ancesters
else List[State]()Option(parent).map(parent => parent :: parent.ancesters).getOrElse(List[State]())Context
StackExchange Code Review Q#10224, answer score: 2
Revisions (0)
No revisions yet.