Skip to content

Commit 8559bd5

Browse files
authored
Merge pull request #123 from exercism/two-bucket
Two bucket
2 parents 0a647ac + 3364cc4 commit 8559bd5

File tree

9 files changed

+3035
-0
lines changed

9 files changed

+3035
-0
lines changed

config.json

+16
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,22 @@
525525
"Exception handling",
526526
"Text formatting"
527527
]
528+
},
529+
{
530+
"uuid": "7dd29a19-08f6-8480-2e01-1f7262d8860a",
531+
"slug": "two-bucket",
532+
"core": false,
533+
"unlocked_by": "pangram",
534+
"difficulty": 6,
535+
"topics": [
536+
"algorithms",
537+
"arrays",
538+
"control-flow-(conditionals)",
539+
"control-flow-(loops)",
540+
"exception-handling",
541+
"games",
542+
"parsing"
543+
]
528544
}
529545
],
530546
"foregone": [],

exercises/two-bucket/README.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Two Bucket
2+
3+
Given two buckets of different size, demonstrate how to measure an exact number of liters by strategically transferring liters of fluid between the buckets.
4+
5+
Since this mathematical problem is fairly subject to interpretation / individual approach, the tests have been written specifically to expect one overarching solution.
6+
7+
To help, the tests provide you with which bucket to fill first. That means, when starting with the larger bucket full, you are NOT allowed at any point to have the smaller bucket full and the larger bucket empty (aka, the opposite starting point); that would defeat the purpose of comparing both approaches!
8+
9+
Your program will take as input:
10+
- the size of bucket one, passed as a numeric value
11+
- the size of bucket two, passed as a numeric value
12+
- the desired number of liters to reach, passed as a numeric value
13+
- which bucket to fill first, passed as a String (either 'one' or 'two')
14+
15+
Your program should determine:
16+
- the total number of "moves" it should take to reach the desired number of liters, including the first fill - expects a numeric value
17+
- which bucket should end up with the desired number of liters (let's say this is bucket A) - expects a String (either 'one' or 'two')
18+
- how many liters are left in the other bucket (bucket B) - expects a numeric value
19+
20+
Note: any time a change is made to either or both buckets counts as one (1) move.
21+
22+
Example:
23+
Bucket one can hold up to 7 liters, and bucket two can hold up to 11 liters. Let's say bucket one, at a given step, is holding 7 liters, and bucket two is holding 8 liters (7,8). If you empty bucket one and make no change to bucket two, leaving you with 0 liters and 8 liters respectively (0,8), that counts as one "move". Instead, if you had poured from bucket one into bucket two until bucket two was full, leaving you with 4 liters in bucket one and 11 liters in bucket two (4,11), that would count as only one "move" as well.
24+
25+
To conclude, the only valid moves are:
26+
- pouring from one bucket to another
27+
- emptying one bucket and doing nothing to the other
28+
- filling one bucket and doing nothing to the other
29+
30+
Referenced with <3 by VestigeJ most of the work was done by [Lindsay](http://lindsaylevine.com).
31+
32+
## Setup
33+
34+
Go through the setup instructions for Typescript to
35+
install the necessary dependencies:
36+
37+
http://exercism.io/languages/typescript
38+
39+
## Requirements
40+
41+
Install assignment dependencies:
42+
43+
```bash
44+
$ npm install
45+
```
46+
47+
## Making the test suite pass
48+
49+
Execute the tests with:
50+
51+
```bash
52+
$ npm test
53+
```
54+
55+
In the test suites all tests but the first have been skipped.
56+
57+
Once you get a test passing, you can enable the next one by
58+
changing `xtest` to `test`.
59+
60+
61+
## Source
62+
63+
Water Pouring Problem [http://demonstrations.wolfram.com/WaterPouringProblem/](http://demonstrations.wolfram.com/WaterPouringProblem/)
64+
65+
## Submitting Incomplete Solutions
66+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

exercises/two-bucket/package.json

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "xtypescript",
3+
"version": "1.0.0",
4+
"description": "Exercism exercises in Typescript.",
5+
"author": "",
6+
"private": true,
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/exercism/xtypescript"
10+
},
11+
"devDependencies": {},
12+
"scripts": {
13+
"test": "tsc --noEmit -p . && jest --no-cache",
14+
"lint": "tsc --noEmit -p . && tslint \"*.ts?(x)\"",
15+
"lintci": "tslint \"*.ts?(x)\" --force"
16+
},
17+
"dependencies": {
18+
"@types/jest": "^21.1.5",
19+
"@types/node": "^8.0.47",
20+
"jest": "^21.2.1",
21+
"ts-jest": "^21.1.3",
22+
"tslint": "^5.8.0",
23+
"typescript": "^2.5.3"
24+
},
25+
"jest": {
26+
"transform": {
27+
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
28+
},
29+
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
30+
"moduleFileExtensions": [
31+
"ts",
32+
"tsx",
33+
"js"
34+
]
35+
}
36+
}

exercises/two-bucket/tsconfig.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es2017",
4+
"module": "commonjs",
5+
"alwaysStrict": true,
6+
"noUnusedLocals": true,
7+
"noUnusedParameters": true,
8+
"noImplicitAny": true,
9+
"strictNullChecks": true,
10+
"preserveConstEnums": true,
11+
"noFallthroughCasesInSwitch":true,
12+
"noImplicitThis":true,
13+
"noImplicitReturns":true,
14+
"sourceMap": true,
15+
"noEmitOnError": true,
16+
"outDir": "./build"
17+
},
18+
"compileOnSave": true,
19+
"exclude": [
20+
"node_modules"
21+
]
22+
}

exercises/two-bucket/tslint.json

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
{
2+
"jsRules": {
3+
"class-name": true,
4+
"comment-format": [
5+
true,
6+
"check-space"
7+
],
8+
"indent": [
9+
true,
10+
"spaces"
11+
],
12+
"no-duplicate-variable": true,
13+
"no-eval": true,
14+
"no-trailing-whitespace": true,
15+
"no-unsafe-finally": true,
16+
"one-line": [
17+
true,
18+
"check-open-brace",
19+
"check-whitespace"
20+
],
21+
"quotemark": [
22+
false,
23+
"double"
24+
],
25+
"semicolon": [
26+
true,
27+
"never"
28+
],
29+
"triple-equals": [
30+
true,
31+
"allow-null-check"
32+
],
33+
"variable-name": [
34+
true,
35+
"ban-keywords"
36+
],
37+
"whitespace": [
38+
true,
39+
"check-branch",
40+
"check-decl",
41+
"check-operator",
42+
"check-separator",
43+
"check-type"
44+
]
45+
},
46+
"rules": {
47+
"class-name": true,
48+
"comment-format": [
49+
true,
50+
"check-space"
51+
],
52+
"indent": [
53+
true,
54+
"spaces"
55+
],
56+
"no-eval": true,
57+
"no-internal-module": true,
58+
"no-trailing-whitespace": true,
59+
"no-unsafe-finally": true,
60+
"no-var-keyword": true,
61+
"one-line": [
62+
true,
63+
"check-open-brace",
64+
"check-whitespace"
65+
],
66+
"semicolon": [
67+
true,
68+
"never"
69+
],
70+
"triple-equals": [
71+
true,
72+
"allow-null-check"
73+
],
74+
"typedef-whitespace": [
75+
true,
76+
{
77+
"call-signature": "nospace",
78+
"index-signature": "nospace",
79+
"parameter": "nospace",
80+
"property-declaration": "nospace",
81+
"variable-declaration": "nospace"
82+
}
83+
],
84+
"variable-name": [
85+
true,
86+
"ban-keywords"
87+
],
88+
"whitespace": [
89+
true,
90+
"check-branch",
91+
"check-decl",
92+
"check-operator",
93+
"check-separator",
94+
"check-type"
95+
],
96+
"no-namespace": true,
97+
"prefer-for-of": true,
98+
"only-arrow-functions": [true, "allow-declarations"],
99+
"no-var-requires": true,
100+
"no-any": true,
101+
"curly": true,
102+
"forin": true,
103+
"no-arg": true,
104+
"label-position": true,
105+
"no-conditional-assignment": true,
106+
"no-console": [true, "log", "error"],
107+
"no-construct": true,
108+
"no-duplicate-variable": true,
109+
"no-empty": true,
110+
"no-invalid-this": [true, "check-function-in-method"],
111+
"no-misused-new": true,
112+
"no-null-keyword": true,
113+
"no-string-literal": true,
114+
"radix": true,
115+
"typeof-compare": true,
116+
"use-isnan": true,
117+
"prefer-const": true,
118+
"array-type": [true, "array-simple"],
119+
"arrow-parens": true,
120+
"new-parens": true,
121+
"no-consecutive-blank-lines": [true,1],
122+
"no-parameter-properties": true,
123+
"no-unnecessary-initializer": true,
124+
"object-literal-shorthand": true,
125+
"object-literal-key-quotes": [true, "as-needed"]
126+
}
127+
}
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
export enum Bucket {
3+
One = "one",
4+
Two = "two"
5+
}
6+
7+
export class TwoBucket {
8+
starter: Bucket
9+
x: number
10+
y: number
11+
z: number
12+
goalBucket: Bucket
13+
otherBucket: number
14+
15+
constructor(x: number, y: number, z: number, starter: Bucket) {
16+
this.starter = starter
17+
this.x = x
18+
this.y = y
19+
this.z = z
20+
}
21+
reachedGoal(measurements: number[]): boolean {
22+
if (measurements[0] === this.z || measurements[1] === this.z) {
23+
if (measurements[0] === this.z) {
24+
this.goalBucket = Bucket.One
25+
this.otherBucket = measurements[1]
26+
} else {
27+
this.goalBucket = Bucket.Two
28+
this.otherBucket = measurements[0]
29+
}
30+
return true
31+
}
32+
return false
33+
}
34+
bigFirst(measurements: number[], moveCount: number, prBool: boolean): number {
35+
let j = measurements[0],
36+
k = measurements[1]
37+
while (!this.reachedGoal(measurements)) {
38+
if (k > this.x && j === 0 && moveCount === 0) {
39+
j = this.x
40+
k = this.y - j
41+
} else if (j === this.x) {
42+
j = 0
43+
} else if (k > this.x && j !== 0 || k > this.x && prBool) {
44+
k -= (this.x - j)
45+
j = this.x
46+
} else if (k > this.x || j === 0) {
47+
j = k
48+
k -= j
49+
} else if (k === 0) {
50+
k = this.y
51+
}
52+
measurements = [j, k]
53+
moveCount++
54+
prBool = !prBool
55+
}
56+
return moveCount
57+
}
58+
smallFirst(measurements: number[], moveCount: number, prBool: boolean): number {
59+
let j = measurements[0],
60+
k = measurements[1]
61+
while (!this.reachedGoal(measurements)) {
62+
if (j === this.x && moveCount === 0) {
63+
j = 0
64+
k = this.x
65+
} else if (j === 0) {
66+
j = this.x
67+
} else if (j === this.x && k < this.y) {
68+
const tempK = k
69+
k + j > this.y ? k = this.y : k = tempK + j
70+
tempK + j > this.y ? j -= (this.y - tempK) : j = 0
71+
} else if (k === this.y) {
72+
k = 0
73+
} else if (k === 0 && j < this.x) {
74+
k = j
75+
j = 0
76+
}
77+
measurements = [j, k]
78+
moveCount++
79+
prBool = !prBool
80+
}
81+
return moveCount
82+
}
83+
moves() {
84+
let j = 0,
85+
k = 0 // j will be running val of bucket one, k = running val of bucket two
86+
this.starter === Bucket.One ? j = this.x : k = this.y
87+
const measurements = [j, k]
88+
let moveCount = 0
89+
const prBool = true // pour / receive boolean - need to pour or receive every other turn
90+
if (this.starter === Bucket.One) {
91+
moveCount = this.smallFirst(measurements, moveCount, prBool)
92+
} else {
93+
moveCount = this.bigFirst(measurements, moveCount, prBool)
94+
}
95+
return moveCount + 1 // accounts for first move made before loop (and moveCount starts at zero before loop)
96+
}
97+
}

0 commit comments

Comments
 (0)