Skip to content

Commit d33020f

Browse files
author
Isaac Ramirez
committed
- implement Counter ADT
- add Flips and Rolls clients
1 parent c92f0e4 commit d33020f

File tree

5 files changed

+204
-0
lines changed

5 files changed

+204
-0
lines changed

src/adts/counter/counter.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Counter
3+
* @classdesc An abstract data type for a simple Counter.
4+
* @see p. 85
5+
*/
6+
class Counter {
7+
constructor (id) {
8+
this._count = 0
9+
// static final string _id
10+
Object.defineProperty(this, '_id', { value: id })
11+
}
12+
13+
/**
14+
* Increments the internal count
15+
*/
16+
increment () {
17+
this._count++
18+
}
19+
20+
/**
21+
* Returns the total count.
22+
* @returns {number} The total count
23+
*/
24+
tally () {
25+
return this._count
26+
}
27+
28+
/**
29+
* Returns the tally and the Counter's id as String.
30+
* @returns {string} The tally + id as string.
31+
* @example
32+
* // 3 heads
33+
*/
34+
toString () {
35+
return `${this.tally()} ${this._id}`
36+
}
37+
}
38+
39+
module.exports = Counter

src/adts/counter/counter.spec.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const Counter = require('./counter')
2+
3+
describe('Unit Tests: Counter ADT', () => {
4+
describe('instance', () => {
5+
beforeEach(() => {
6+
this.name = 'test'
7+
this.counter = new Counter(this.name)
8+
})
9+
10+
it('should not allow to change its name', () => {
11+
this.counter._id = 'new name'
12+
13+
expect(this.counter._id).toBe(this.name)
14+
})
15+
16+
describe('increment method', () => {
17+
it('should increment the `count`', () => {
18+
const trials = 1000
19+
20+
for (let i = 0; i < trials; i++) {
21+
this.counter.increment()
22+
}
23+
24+
expect(this.counter._count).toEqual(trials)
25+
})
26+
})
27+
28+
describe('tally method', () => {
29+
it('should return the total `count`', () => {
30+
const trials = 1000
31+
32+
for (let i = 0; i < trials; i++) {
33+
this.counter.increment()
34+
}
35+
36+
expect(this.counter.tally()).toEqual(trials)
37+
})
38+
})
39+
40+
describe('toString method', () => {
41+
it('should return a formatted string with the count and id values', () => {
42+
this.counter.increment()
43+
this.counter.increment()
44+
this.counter.increment()
45+
const expectedStr = `3 ${this.name}`
46+
47+
expect(String(this.counter)).toBe(expectedStr)
48+
})
49+
})
50+
})
51+
})

src/adts/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
Counter: require('./counter/counter')
3+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const { StdOut, StdRandom } = require('../../libs')
2+
const { Counter } = require('../../adts')
3+
4+
/**
5+
* Flips
6+
* @classdesc Counter Client
7+
* @see p. 70, 71, 85, 89
8+
*/
9+
class Flips {
10+
/**
11+
* Returns the counter with the max tally.
12+
* @param {Counter} counterX Counter X
13+
* @param {Counter} counterY Counter Y
14+
*/
15+
static max (counterX, counterY) {
16+
if (counterX.tally() > counterY.tally()) {
17+
return counterX
18+
} else {
19+
return counterY
20+
}
21+
}
22+
23+
/**
24+
* Simulates the flips of a coin and computes the delta.
25+
* @param {[]} args [trials]
26+
* @example
27+
* ```sh
28+
* $ node flips.client.js 1000
29+
* 490 heads
30+
* 510 tails
31+
* delta: 20
32+
* 510 tails wins
33+
* ```
34+
*/
35+
static main (args) {
36+
const trials = parseInt(args[0], 10)
37+
const heads = new Counter('heads')
38+
const tails = new Counter('tails')
39+
40+
for (let i = 0; i < trials; i++) {
41+
if (StdRandom.bernoulli(0.5)) {
42+
heads.increment()
43+
} else {
44+
tails.increment()
45+
}
46+
}
47+
48+
StdOut.println(heads.toString())
49+
StdOut.println(tails.toString())
50+
51+
const delta = heads.tally() - tails.tally()
52+
53+
StdOut.println(`delta: ${Math.abs(delta)}`)
54+
55+
if (heads.tally() === tails.tally()) {
56+
StdOut.println(`It's a Tie!`)
57+
} else {
58+
StdOut.println(`${Flips.max(heads, tails)} wins`)
59+
}
60+
}
61+
}
62+
63+
// Execution
64+
// ==============================
65+
Flips.main(process.argv.slice(2))
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const { StdOut, StdRandom } = require('../../libs')
2+
const { Counter } = require('../../adts')
3+
4+
/**
5+
* Rolls
6+
* @classdesc Counter client
7+
* @see p. 72
8+
*/
9+
class Rolls {
10+
/**
11+
* Simulates rolls of a die
12+
* @param {[]} args [trials]
13+
* @example
14+
* ```sh
15+
* $ node rolls.client.js 100000
16+
* 16399 1s
17+
* 16785 2s
18+
* 16661 3s
19+
* 16511 4s
20+
* 16904 5s
21+
* 16740 6s
22+
* ```
23+
*/
24+
static main (args) {
25+
const trials = parseInt(args[0], 10)
26+
const SIDES = 6
27+
const rolls = new Array(SIDES + 1)
28+
29+
for (let i = 1; i <= SIDES; i++) {
30+
rolls[i] = new Counter(`${i}s`)
31+
}
32+
33+
for (let t = 0; t < trials; t++) {
34+
const result = StdRandom.uniform(1, SIDES + 1)
35+
rolls[result].increment()
36+
}
37+
38+
for (let i = 1; i <= SIDES; i++) {
39+
StdOut.println(String(rolls[i]))
40+
}
41+
}
42+
}
43+
44+
// Execution
45+
// ==============================
46+
Rolls.main(process.argv.slice(2))

0 commit comments

Comments
 (0)