From 55d981072746de97caac1b32a1284143286b0437 Mon Sep 17 00:00:00 2001 From: Staszek Welsh Date: Thu, 28 Apr 2022 19:50:17 +0100 Subject: [PATCH] Handle edge case in LZ compression code and fix docs --- doc/source/basicgameplay/codingcontracts.rst | 28 ++++++++--------- src/data/codingcontracttypes.ts | 33 ++++++++++---------- src/utils/CompressionContracts.ts | 7 +++++ 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/doc/source/basicgameplay/codingcontracts.rst b/doc/source/basicgameplay/codingcontracts.rst index 715b2fb31..e8fdabbd9 100644 --- a/doc/source/basicgameplay/codingcontracts.rst +++ b/doc/source/basicgameplay/codingcontracts.rst @@ -336,12 +336,12 @@ The list contains the name of (i.e. the value returned by | | | | | | | You are given an LZ-encoded string. Decode it and output the original string. | | | | | -| | | Example: decoding '5aaabc340533bca' chunk-by-chunk | -| | | 5aaabc -> aaabc | -| | | 5aaabc34 -> aaabcaab | -| | | 5aaabc340 -> aaabcaab | -| | | 5aaabc34053 -> aaabcaabaabaa | -| | | 5aaabc340533bca -> aaabcaabaabaabca | +| | | Example: decoding '5aaabb450723abb' chunk-by-chunk | +| | | 5aaabb -> aaabb | +| | | 5aaabb45 -> aaabbaaab | +| | | 5aaabb450 -> aaabbaaab | +| | | 5aaabb45072 -> aaabbaaababababa | +| | | 5aaabb450723abb -> aaabbaaababababaabb | +-----------------------------------------+------------------------------------------------------------------------------------------+ | Compression III: LZ Compression | | Lempel-Ziv (LZ) compression is a data compression technique which encodes data using | | | | references to earlier parts of the data. In this variant of LZ, data is encoded in two | @@ -361,12 +361,12 @@ The list contains the name of (i.e. the value returned by | | | possible output length. | | | | | | | | Examples (some have other possible encodings of minimal length): | -| | | abracadabra -> 7abracad47 | -| | | mississippi -> 4miss433ppi | -| | | aAAaAAaAaAA -> 3aAA53035 | -| | | 2718281828 -> 627182844 | -| | | abcdefghijk -> 9abcdefghi02jk | -| | | aaaaaaaaaaa -> 1a911a | -| | | aaaaaaaaaaaa -> 1a912aa | -| | | aaaaaaaaaaaaa -> 1a91031 | +| | | abracadabra -> 7abracad47 | +| | | mississippi -> 4miss433ppi | +| | | aAAaAAaAaAA -> 3aAA53035 | +| | | 2718281828 -> 627182844 | +| | | abcdefghijk -> 9abcdefghi02jk | +| | | aaaaaaaaaaaa -> 3aaa91 | +| | | aaaaaaaaaaaaa -> 1a91031 | +| | | aaaaaaaaaaaaaa -> 1a91041 | +-----------------------------------------+------------------------------------------------------------------------------------------+ diff --git a/src/data/codingcontracttypes.ts b/src/data/codingcontracttypes.ts index a28f8d2d3..244cc35b9 100644 --- a/src/data/codingcontracttypes.ts +++ b/src/data/codingcontracttypes.ts @@ -1532,7 +1532,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ length += 2; } } - return ans.length === length; + + return ans.length <= length; }, }, { @@ -1555,12 +1556,12 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ "You are given the following LZ-encoded string:\n", `    ${compressed}\n`, "Decode it and output the original string.\n\n", - "Example: decoding '5aaabc340533bca' chunk-by-chunk\n", - "    5aaabc           ->  aaabc\n", - "    5aaabc34         ->  aaabcaab\n", - "    5aaabc340        ->  aaabcaab\n", - "    5aaabc34053      ->  aaabcaabaabaa\n", - "    5aaabc340533bca  ->  aaabcaabaabaabca", + "Example: decoding '5aaabb450723abb' chunk-by-chunk\n", + "    5aaabb           ->  aaabb\n", + "    5aaabb45         ->  aaabbaaab\n", + "    5aaabb450        ->  aaabbaaab\n", + "    5aaabb45072      ->  aaabbaaababababa\n", + "    5aaabb450723abb  ->  aaabbaaababababaabb", ].join(" "); }, gen: (): string => { @@ -1591,21 +1592,21 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [ `    ${plaintext}\n`, "Encode it using Lempel-Ziv encoding with the minimum possible output length.\n\n", "Examples (some have other possible encodings of minimal length):\n", - "    abracadabra    ->  7abracad47\n", - "    mississippi    ->  4miss433ppi\n", - "    aAAaAAaAaAA    ->  3aAA53035\n", - "    2718281828     ->  627182844\n", - "    abcdefghijk    ->  9abcdefghi02jk\n", - "    aaaaaaaaaaa    ->  1a911a\n", - "    aaaaaaaaaaaa   ->  1a912aa\n", - "    aaaaaaaaaaaaa  ->  1a91031", + "    abracadabra     ->  7abracad47\n", + "    mississippi     ->  4miss433ppi\n", + "    aAAaAAaAaAA     ->  3aAA53035\n", + "    2718281828      ->  627182844\n", + "    abcdefghijk     ->  9abcdefghi02jk\n", + "    aaaaaaaaaaaa    ->  3aaa91\n", + "    aaaaaaaaaaaaa   ->  1a91031\n", + "    aaaaaaaaaaaaaa  ->  1a91041", ].join(" "); }, gen: (): string => { return comprLZGenerate(); }, solver: (plain: string, ans: string): boolean => { - return comprLZDecode(ans) === plain && ans.length === comprLZEncode(plain).length; + return comprLZDecode(ans) === plain && ans.length <= comprLZEncode(plain).length; }, }, ]; diff --git a/src/utils/CompressionContracts.ts b/src/utils/CompressionContracts.ts index 525157ded..c800b1008 100644 --- a/src/utils/CompressionContracts.ts +++ b/src/utils/CompressionContracts.ts @@ -105,6 +105,13 @@ export function comprLZEncode(plain: string): string { // start new literal set(new_state, 0, 1, string + length + offset); + + // end current backreference and start new backreference + for (let new_offset = 1; new_offset <= Math.min(9, i); ++new_offset) { + if (plain[i - new_offset] === c) { + set(new_state, new_offset, 1, string + length + offset + "0"); + } + } } }