Skip to content

Commit 2a41cb7

Browse files
feat: Add Pop Count (#72)
1 parent da0acc9 commit 2a41cb7

File tree

14 files changed

+279
-0
lines changed

14 files changed

+279
-0
lines changed

config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,13 @@
174174
"practices": [],
175175
"prerequisites": [],
176176
"difficulty": 2
177+
}, {
178+
"slug": "pop-count",
179+
"name": "Pop Count",
180+
"uuid": "233fde6a-79d9-4d90-8f94-2a0519352a5c",
181+
"practices": [],
182+
"prerequisites": [],
183+
"difficulty": 4
177184
}, {
178185
"slug": "pangram",
179186
"name": "Pangram",
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Reserved Addresses
2+
3+
No linear memory is required for this exercise.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Instructions
2+
3+
Your task is to count the number of 1 bits in the binary representation of a number.
4+
5+
## Restrictions
6+
7+
Keep your hands off that bit-count functionality provided by your standard library!
8+
Solve this one yourself using other basic tools instead.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Introduction
2+
3+
Your friend Eliud inherited a farm from her grandma Tigist.
4+
Her granny was an inventor and had a tendency to build things in an overly complicated manner.
5+
The chicken coop has a digital display showing an encoded number representing the positions of all eggs that could be picked up.
6+
7+
Eliud is asking you to write a program that shows the actual number of eggs in the coop.
8+
9+
The position information encoding is calculated as follows:
10+
11+
1. Scan the potential egg-laying spots and mark down a `1` for an existing egg or a `0` for an empty spot.
12+
2. Convert the number from binary to decimal.
13+
3. Show the result on the display.
14+
15+
Example 1:
16+
17+
```text
18+
Chicken Coop:
19+
_ _ _ _ _ _ _
20+
|E| |E|E| | |E|
21+
22+
Resulting Binary:
23+
1 0 1 1 0 0 1
24+
25+
Decimal number on the display:
26+
89
27+
28+
Actual eggs in the coop:
29+
4
30+
```
31+
32+
Example 2:
33+
34+
```text
35+
Chicken Coop:
36+
_ _ _ _ _ _ _ _
37+
| | | |E| | | | |
38+
39+
Resulting Binary:
40+
0 0 0 1 0 0 0 0
41+
42+
Decimal number on the display:
43+
16
44+
45+
Actual eggs in the coop:
46+
1
47+
```
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"root": true,
3+
"extends": "@exercism/eslint-config-javascript",
4+
"env": {
5+
"jest": true
6+
},
7+
"overrides": [
8+
{
9+
"files": [
10+
"*.spec.js"
11+
],
12+
"excludedFiles": [
13+
"custom.spec.js"
14+
],
15+
"extends": "@exercism/eslint-config-javascript/maintainers"
16+
}
17+
]
18+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"authors": [
3+
"keiravillekode"
4+
],
5+
"files": {
6+
"solution": [
7+
"pop-count.wat"
8+
],
9+
"test": [
10+
"pop-count.spec.js"
11+
],
12+
"example": [
13+
".meta/proof.ci.wat"
14+
]
15+
},
16+
"blurb": "Count the 1 bits in a number",
17+
"source": "Christian Willner, Eric Willigers",
18+
"source_url": "https://forum.exercism.org/t/new-exercise-suggestion-pop-count/7632/5",
19+
"custom": {
20+
"version.tests.compatibility": "jest-27",
21+
"flag.tests.task-per-describe": false,
22+
"flag.tests.may-run-long": false,
23+
"flag.tests.includes-optional": false
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(module
2+
(func (export "eggCount") (param $number i32) (result i32)
3+
(local $remaining i32)
4+
(local $count i32)
5+
6+
(if (i32.eq (local.get $number) (i32.const 0))(then
7+
(return (i32.const 0))
8+
))
9+
10+
(local.set $remaining (local.get $number))
11+
(local.set $count (i32.const 0))
12+
13+
;; do while $remaining != 0
14+
(loop
15+
;; Clear least-significant 1 bit using
16+
;; $remaining -= $remaining & -$remaining
17+
(local.set $remaining (i32.sub (local.get $remaining) (i32.and (local.get $remaining) (i32.sub (i32.const 0) (local.get $remaining)))))
18+
(local.set $count (i32.add (local.get $count) (i32.const 1)))
19+
(br_if 0 (i32.ne (local.get $remaining) (i32.const 0)))
20+
)
21+
22+
(return (local.get $count))
23+
)
24+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# This is an auto-generated file. Regular comments will be removed when this
2+
# file is regenerated. Regenerating will not touch any manually added keys,
3+
# so comments can be added in a "comment" key.
4+
5+
[559e789d-07d1-4422-9004-3b699f83bca3]
6+
description = "0 eggs"
7+
8+
[97223282-f71e-490c-92f0-b3ec9e275aba]
9+
description = "1 egg"
10+
11+
[1f8fd18f-26e9-4144-9a0e-57cdfc4f4ff5]
12+
description = "4 eggs"
13+
14+
[0c18be92-a498-4ef2-bcbb-28ac4b06cb81]
15+
description = "13 eggs"

exercises/practice/pop-count/.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
audit=false

exercises/practice/pop-count/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Exercism
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export default {
2+
presets: ["@exercism/babel-preset-javascript"],
3+
plugins: [],
4+
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "@exercism/wasm-pop-count",
3+
"description": "Exercism exercises in WebAssembly.",
4+
"type": "module",
5+
"private": true,
6+
"license": "MIT",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/exercism/wasm",
10+
"directory": "exercises/practice/pop-count"
11+
},
12+
"jest": {
13+
"maxWorkers": 1
14+
},
15+
"devDependencies": {
16+
"@babel/core": "^7.20.12",
17+
"@exercism/babel-preset-javascript": "^0.2.1",
18+
"@exercism/eslint-config-javascript": "^0.6.0",
19+
"@types/jest": "^29.4.0",
20+
"@types/node": "^18.13.0",
21+
"babel-jest": "^29.4.2",
22+
"core-js": "^3.27.2",
23+
"eslint": "^8.34.0",
24+
"jest": "^29.4.2"
25+
},
26+
"dependencies": {
27+
"@exercism/wasm-lib": "^0.1.0"
28+
},
29+
"scripts": {
30+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js ./*",
31+
"watch": "node --experimental-vm-modules node_modules/jest/bin/jest.js --watch ./*",
32+
"lint": "eslint ."
33+
}
34+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { compileWat, WasmRunner } from "@exercism/wasm-lib";
2+
3+
let wasmModule;
4+
let currentInstance;
5+
6+
beforeAll(async () => {
7+
try {
8+
const watPath = new URL("./pop-count.wat", import.meta.url);
9+
const { buffer } = await compileWat(watPath);
10+
wasmModule = await WebAssembly.compile(buffer);
11+
} catch (err) {
12+
console.log(`Error compiling *.wat: ${err}`);
13+
process.exit(1);
14+
}
15+
});
16+
17+
describe("eggCount()", () => {
18+
beforeEach(async () => {
19+
currentInstance = null;
20+
21+
if (!wasmModule) {
22+
return Promise.reject();
23+
}
24+
try {
25+
currentInstance = await new WasmRunner(wasmModule);
26+
return Promise.resolve();
27+
} catch (err) {
28+
console.log(`Error instantiating WebAssembly module: ${err}`);
29+
return Promise.reject();
30+
}
31+
});
32+
33+
test("0 eggs", () => {
34+
expect(currentInstance.exports.eggCount(0)).toEqual(0);
35+
});
36+
37+
xtest("1 egg", () => {
38+
expect(currentInstance.exports.eggCount(16)).toEqual(1);
39+
});
40+
41+
xtest("4 eggs", () => {
42+
expect(currentInstance.exports.eggCount(89)).toEqual(4);
43+
});
44+
45+
xtest("13 eggs", () => {
46+
expect(currentInstance.exports.eggCount(2000000000)).toEqual(13);
47+
});
48+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
(module
2+
(func (export "eggCount") (param $number i32) (result i32)
3+
(local $remaining i32)
4+
(local $count i32)
5+
6+
(if (i32.eq (local.get $number) (i32.const 0))(then
7+
(return (i32.const 0))
8+
))
9+
10+
(local.set $remaining (i32.const 0))
11+
(local.set $count (i32.const 0))
12+
13+
;; do while $remaining != 0
14+
(loop
15+
;; Clear least-significant 1 bit using
16+
;; $remaining -= $remaining & -$remaining
17+
(local.set $remaining (i32.sub (local.get $remaining) (i32.and (local.get $remaining) (i32.sub (i32.const 0) (local.get $remaining)))))
18+
(local.set $count (i32.add (local.get $count) (i32.const 1)))
19+
(br_if 0 (i32.ne (local.get $remaining) (i32.const 0)))
20+
)
21+
22+
(return (local.get $count))
23+
)
24+
)

0 commit comments

Comments
 (0)