Skip to content

Commit bd75f68

Browse files
committed
Merge branch 'release/1.1.0'
2 parents 58db133 + e594419 commit bd75f68

9 files changed

Lines changed: 6994 additions & 1 deletion

File tree

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"license" : "MIT",
3+
"scripts": {
4+
"test": "jest --watchAll"
5+
},
6+
"devDependencies": {
7+
"jest": "^22.4.3"
8+
}
9+
}
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
'use strict'
2+
3+
//
4+
// solve
5+
// should only return 'POSSIBLE' or 'IMPOSSIBLE'
6+
//
7+
function solve(prob) {
8+
if (prob.numChips === 0) {
9+
return 'POSSIBLE'
10+
}
11+
12+
const chipsPerPiece = prob.numChips / prob.numPieces
13+
if (!Number.isInteger(chipsPerPiece)) {
14+
return 'IMPOSSIBLE'
15+
}
16+
17+
// start row processing
18+
const HChipCount = prob.numChips / (prob.H + 1)
19+
let cumuRowCutChips = 0
20+
let rowCut = []
21+
for (let i = 0; i < prob.R; i++) {
22+
cumuRowCutChips += prob.rowChips[i]
23+
24+
if (cumuRowCutChips === HChipCount) {
25+
rowCut.push(i)
26+
cumuRowCutChips = 0
27+
}
28+
29+
if (cumuRowCutChips > HChipCount) {
30+
return 'IMPOSSIBLE'
31+
}
32+
}
33+
34+
if (rowCut.length !== prob.H + 1) {
35+
return 'IMPOSSIBLE'
36+
}
37+
38+
// get pieceChips set to all 0.
39+
let pieceChips = rowCut.map(rc => 0)
40+
41+
// start column and piece processing
42+
const VChipCount = prob.numChips / (prob.V + 1)
43+
let cumuColCutChips = 0
44+
let colCut = []
45+
for (let j = 0; j < prob.C; j++) {
46+
cumuColCutChips += prob.colChips[j]
47+
48+
let rowCutIndex = 0
49+
for (let i = 0; i < prob.R; i++) {
50+
if (prob.rows[i][j] === '@') {
51+
pieceChips[rowCutIndex] += 1
52+
}
53+
54+
if (i === rowCut[rowCutIndex]) {
55+
rowCutIndex += 1
56+
}
57+
}
58+
59+
if (cumuColCutChips === VChipCount) {
60+
if (!pieceChips.every(pieceChip => pieceChip === chipsPerPiece)) {
61+
return 'IMPOSSIBLE'
62+
}
63+
64+
colCut.push(j)
65+
cumuColCutChips = 0
66+
pieceChips = rowCut.map(rc => 0)
67+
}
68+
69+
if (cumuColCutChips > VChipCount) {
70+
return 'IMPOSSIBLE'
71+
}
72+
}
73+
74+
if (colCut.length !== prob.V + 1) {
75+
return 'IMPOSSIBLE'
76+
}
77+
78+
return 'POSSIBLE'
79+
}
80+
81+
function canSimpleDivide(numChips, numPieces) {
82+
if (numChips % numPieces !== 0) {
83+
return false
84+
}
85+
return true
86+
}
87+
88+
//
89+
// processCases
90+
//
91+
function processCases(probs) {
92+
for (let index = 0; index < probs.length; index++) {
93+
const result = solve(probs[index])
94+
console.log(`Case #${index + 1}: ${result}`)
95+
}
96+
}
97+
98+
//
99+
// CaseParser
100+
//
101+
class CaseParser {
102+
constructor(caseNumber) {
103+
this.caseNo = caseNumber
104+
this.R = 0
105+
this.C = 0
106+
this.H = 0
107+
this.V = 0
108+
this.rows = []
109+
110+
this.rowChips = []
111+
this.colChips = []
112+
this.numChips = 0
113+
this.numPieces = 0
114+
115+
this.currentR = 0
116+
this.state = '1'
117+
}
118+
119+
readline(line) {
120+
switch (this.state) {
121+
case '1': {
122+
const firstLine = line.split(' ')
123+
this.R = parseInt(firstLine[0])
124+
this.C = parseInt(firstLine[1])
125+
this.H = parseInt(firstLine[2])
126+
this.V = parseInt(firstLine[3])
127+
128+
for (let i = 0; i < this.C; i++) {
129+
this.colChips.push(0)
130+
}
131+
132+
this.numPieces = (this.H + 1) * (this.V + 1)
133+
134+
this.state = 'rows'
135+
break
136+
}
137+
138+
case 'rows': {
139+
const chars = line.split('')
140+
this.rows.push(chars)
141+
142+
const chipCount = chars.filter(char => char === '@').length
143+
this.rowChips.push(chipCount)
144+
145+
for (let i = 0; i < chars.length; i++) {
146+
if (chars[i] === '@') {
147+
this.colChips[i] += 1
148+
}
149+
}
150+
151+
this.numChips += chipCount
152+
153+
this.currentR += 1
154+
155+
if (this.currentR === this.R) {
156+
this.state = 'done'
157+
}
158+
break
159+
}
160+
}
161+
}
162+
163+
isComplete() {
164+
return (this.state === 'done')
165+
}
166+
167+
getCase() {
168+
return {
169+
caseNo: this.caseNo,
170+
R: this.R,
171+
C: this.C,
172+
H: this.H,
173+
V: this.V,
174+
rows: this.rows,
175+
rowChips: this.rowChips,
176+
colChips: this.colChips,
177+
numChips: this.numChips,
178+
numPieces: this.numPieces
179+
}
180+
}
181+
}
182+
183+
//
184+
// ProblemParser
185+
//
186+
class ProblemParser {
187+
constructor() {
188+
this.t = 0
189+
this.currentT = 0
190+
this.cases = []
191+
this.caseParser = new CaseParser(1)
192+
this.state = 't'
193+
}
194+
195+
readline(line) {
196+
switch (this.state) {
197+
case 't': {
198+
this.t = parseInt(line)
199+
this.state = 'case'
200+
break
201+
}
202+
203+
case 'case': {
204+
this.caseParser.readline(line)
205+
206+
if (this.caseParser.isComplete()) {
207+
this.cases.push(this.caseParser.getCase())
208+
this.currentT += 1
209+
this.caseParser = new CaseParser(this.currentT + 1)
210+
}
211+
212+
break
213+
}
214+
}
215+
216+
if (this.currentT === this.t) {
217+
this.state = 'done'
218+
}
219+
}
220+
221+
isComplete() {
222+
return (this.state === 'done')
223+
}
224+
225+
getCases() {
226+
return this.cases
227+
}
228+
}
229+
230+
//
231+
// Main
232+
//
233+
function main() {
234+
const readline = require('readline')
235+
const problemParser = new ProblemParser()
236+
237+
const rl = readline.createInterface({
238+
input: process.stdin,
239+
output: process.stdout
240+
})
241+
242+
rl.on('line', (line) => {
243+
problemParser.readline(line)
244+
245+
if (problemParser.isComplete()) {
246+
rl.close()
247+
}
248+
}).on('close', () => {
249+
processCases(problemParser.getCases())
250+
}
251+
)
252+
}
253+
254+
if (!module.parent) {
255+
main()
256+
}
257+
258+
module.exports = {
259+
solve,
260+
CaseParser
261+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
const {solve, CaseParser} = require('./solution')
2+
3+
test('1', () => {
4+
const caseParser = new CaseParser(1)
5+
caseParser.readline('3 6 1 1')
6+
caseParser.readline('.@@..@')
7+
caseParser.readline('.....@')
8+
caseParser.readline('@.@.@@')
9+
10+
const result = solve(caseParser.getCase())
11+
12+
expect(result).toBe('POSSIBLE')
13+
})
14+
15+
test('2', () => {
16+
const caseParser = new CaseParser(2)
17+
caseParser.readline('4 3 1 1')
18+
caseParser.readline('@@@')
19+
caseParser.readline('@.@')
20+
caseParser.readline('@.@')
21+
caseParser.readline('@@@')
22+
23+
const result = solve(caseParser.getCase())
24+
25+
expect(result).toBe('IMPOSSIBLE')
26+
})
27+
28+
test('3', () => {
29+
const caseParser = new CaseParser(3)
30+
caseParser.readline('4 5 1 1')
31+
caseParser.readline('.....')
32+
caseParser.readline('.....')
33+
caseParser.readline('.....')
34+
caseParser.readline('.....')
35+
36+
const result = solve(caseParser.getCase())
37+
38+
expect(result).toBe('POSSIBLE')
39+
})
40+
41+
test('4', () => {
42+
const caseParser = new CaseParser(4)
43+
caseParser.readline('4 4 1 1')
44+
caseParser.readline('..@@')
45+
caseParser.readline('..@@')
46+
caseParser.readline('@@..')
47+
caseParser.readline('@@..')
48+
49+
const result = solve(caseParser.getCase())
50+
51+
expect(result).toBe('IMPOSSIBLE')
52+
})
53+
54+
test('5', () => {
55+
const caseParser = new CaseParser(5)
56+
caseParser.readline('3 4 2 2')
57+
caseParser.readline('@.@@')
58+
caseParser.readline('@@.@')
59+
caseParser.readline('@.@@')
60+
61+
const result = solve(caseParser.getCase())
62+
63+
expect(result).toBe('POSSIBLE')
64+
})
65+
66+
test('6', () => {
67+
const caseParser = new CaseParser(6)
68+
caseParser.readline('3 4 1 2')
69+
caseParser.readline('.@.@')
70+
caseParser.readline('@.@.')
71+
caseParser.readline('.@.@')
72+
73+
const result = solve(caseParser.getCase())
74+
75+
expect(result).toBe('IMPOSSIBLE')
76+
})

0 commit comments

Comments
 (0)