Cockroach Salad

Description

Cockroach Salad is a card game designed by Jacques Zeimet in 2007. The rules are as follows:

  • When you play a card, if there is no restriction, you must say the name of the vegetable printed on your card.
  • However, you can not say the same name twice in a row. If you can not say the correct vegetable, you must say say an arbitrary different vegetable.
  • One vegetable name is banned and you can not say it. If you would need to say it, say an arbitrary different vegetable.

In this challenge, we’ll have 4 vegetables: a (lettuce), b (tomato), c (cucumber), and d (grape). Given the order you draw cards from the deck, output what vegetables you would say out out. If there are capital letters A, B, C, D in the input, those mean that vegetable is now banned. Do not include these in the output. One vegetable is banned at a time, a new banned vegetable replaces the last one.

Worked Out Example

Lets take the input: aabAaacd

  • First, we see an a. This is valid so we output a.
  • Then we get an a again. We can not say a twice in a row, so we output b. We could have also outputted c or d and it would also be valid.
  • Next, we see b. However, we can’t output b twice in a row so we output d. We could have also outputted a or c.
  • Now we see an A. This is a capital so it means a is now banned. We output nothing.
  • Then we get an a, but a is banned. d was last outputted so we can’t print that either. So we output c.
  • Then another a. We output d, since a is banned.
  • Next, c. c is valid so we must output c.
  • Next, d, which is also valid.

So the final output could be abadcdcd, but there are other valid options.

Each line in the input will be one string.

Judge

(async function*(context: Context): Challenge {
	function validateOutput(input: string, output: string): boolean {
		output = output.trimEnd();
		
		let i=0;
		let previous = '';
		let banned = '';
		
		for (const character of input) {
			if (character == character.toLocaleUpperCase()) {
				banned = character.toLocaleLowerCase();
				continue;
			}
			if (character != previous && character != banned) {
				if (output[i] != character) {
					return false;
				}
			}
			else if (output[i] == previous || output[i] == banned) {
				console.error(`${output[i]} ${previous} ${banned}`);
				return false
			}
			previous = output[i];
			i++;
		}

		return i==output.length;
		
	}

	function solve(input: string): string {
		let previous = '';
		let banned = '';
		let output = '';

		for (const character of input) {
			if (character.toLocaleUpperCase() == character) {
				banned = character.toLocaleLowerCase();
				continue;
			}
			if (character != banned && character != previous) {
				output += character;
				previous = character;
				continue;
			} else {
				let char = ['a','b','c','d'].filter(i=>i!=previous && i!=banned)[0];
				previous = char;
				output += char;
				continue;
			}
			
		}
		return output;
	}

	function randomString(chars: string, length: number): string {
		let string = '';

		for (let i=0; i<length; i++) {
			string += chars[Math.floor(Math.random() * chars.length)]
		}

		return string;
	}

	class FakeSolve {
		input: string;
		output: string;
		
		constructor(input: string, output: string) {
			this.input = input;
			this.output = output;
		}

		toString() {
			return this.output;
		}
	}

	let randomTestCases = [];

	for (let i=0; i<100; i++) {
		randomTestCases.push(randomString('aaaabbbbccccddddABCD', Math.floor(Math.random() * 100) + 25))
	}


	// Automatically shuffle and deal test cases over multiple runs
	yield* context.runTestCases(
		randomTestCases.map(
			i=>[i, new FakeSolve(i, solve(i))] as [string,FakeSolve]
		),
		{
			compareFunction(a, b) {
				return validateOutput(b.input, a)
			}
		}
	);
	// Finally, the challenge is passed if no test cases failed
	return context.noFailures();
})

Example Code

	function solve(input) {
		let previous = '';
		let banned = '';
		let output = '';

		for (const character of input) {
			if (character.toLocaleUpperCase() == character) {
				banned = character.toLocaleLowerCase();
				continue;
			}
			if (character != banned && character != previous) {
				output += character;
				previous = character;
				continue;
			} else {
				let char = ['a','b','c','d'].filter(i=>i!=previous && i!=banned)[0];
				previous = char;
				output += char;
				continue;
			}
			
		}
		return output;
	}

process.stdin.on('data',i=>(''+i).split('\n').forEach(k=>console.log(solve(k))))

Comments