RosettaCodeData/Task/ABC-problem/MAXScript/abc-problem-1.max

99 lines
3.6 KiB
Plaintext

-- This is the blocks array
global GlobalBlocks = #("BO","XK","DQ","CP","NA", \
"GT","RE","TG","QD","FS", \
"JW","HU","VI","AN","OB", \
"ER","FS","LY","PC","ZM")
-- This function returns true if "_str" is part of "_word", false otherwise
fn occurs _str _word =
(
if _str != undefined and _word != undefined then
(
matchpattern _word pattern:("*"+_str+"*")
) else return false
)
-- This is the main function
fn isWordPossible word blocks: = -- blocks is a keyword argument
(
word = toupper word -- convert the string to upper case, to make it case insensitive
if blocks == unsupplied do blocks = GlobalBlocks
-- if blocks (keyword argument) is unsupplied, use the global blocks array (this is for recursion)
blocks = deepcopy blocks
local pos = 1 -- start at the beginning of the word
local solvedLetters = #() -- this array stores the indices of solved letters
while pos <= word.count do -- loop through every character in the word
(
local possibleBlocks = #() -- this array stores the blocks which can be used to make that letter
for b = 1 to Blocks.count do -- this loop finds all the possible blocks that can be used to make that letter
(
if occurs word[pos] blocks[b] do
(
appendifunique possibleBlocks b
)
)
if possibleBlocks.count > 0 then -- if it found any blocks
(
if possibleBlocks.count == 1 then -- if it found one block, then continue
(
appendifunique solvedLetters pos
deleteitem blocks possibleblocks[1]
pos += 1
)
else -- if it found more than one
(
for b = 1 to possibleBlocks.count do -- loop through every possible block
(
local possibleBlock = blocks[possibleBlocks[b]]
local blockFirstLetter = possibleBlock[1]
local blockSecondLetter = possibleBlock[2]
local matchingLetter = if blockFirstLetter == word[pos] then 1 else 2
-- ^ this is the index of the matching letter on the block
local notMatchingIndex = if matchingLetter == 1 then 2 else 1
local notMatchingLetter = possibleBlock[notMatchingIndex]
-- ^ this is the other letter on the block
if occurs notMatchingLetter (substring word (pos+1) -1) then
( -- if the other letter occurs in the rest of the word
local removedBlocks = deepcopy blocks -- copy the current blocks array
deleteitem removedBlocks possibleBlocks[b] -- remove the item from the copied array
-- recursively check if the word is possible if that block is taken away from the array:
if (isWordPossible (substring word (pos+1) -1) blocks:removedBlocks) then
( -- if it is, then remove the block and move to next character
appendifunique solvedLetters pos
deleteitem blocks possibleblocks[1]
pos += 1
exit
)
else
( -- if it isn't and it looped through every possible block, then the word is not possible
if b == possibleBlocks.count do return false
)
)
else
( -- if the other letter on this block doesn't occur in the rest of the word, then the letter is solved, continue
appendifunique solvedLetters pos
deleteitem blocks possibleblocks[b]
pos += 1
exit
)
)
)
) else return false -- if it didn't find any blocks, then return false
)
makeuniquearray solvedLetters -- make sure there are no duplicates in the solved array
if solvedLetters.count != word.count then return false -- if number of solved letters is not equal to word length
else
( -- this checks if all the solved letters are the same as the word
check = ""
for bit in solvedLetters do append check word[bit]
if check == word then return true else return false
)
)