2015-10-06 1 views
0

Я пытаюсь решить это упражнение:Неправильный выход простого решения упражнений Haskell

Вам дают последовательность N шаров в 4-х цветах: красный, зеленый, желтый и синий . Последовательность полна цветы, если и только если все следующих условий:

  • Есть так много красных шаров как зеленые шары.
  • Есть так много желтых шаров, как синие шары.
  • разница между количеством красных шаров и зелеными шарами в каждом префиксе последовательности не превосходит 1.
  • разницы между количеством желтых шаров и синими шарами в каждом префиксе последовательности не превосходит 1.

Ваша задача - написать программу, которая для данной последовательности печатает True, если она полна цветов, в противном случае она печатает False.

Мое решение до сих пор:

module Main where 

import Control.Monad 

main = do 
    s <- readLn :: IO Int 
    elements <- replicateM s getLine 
    let result = map checkColours elements 
    mapM (putStrLn . show) result 

checkColours :: String -> Bool 
checkColours string = isFullOfColors 0 0 0 0 string 

isFullOfColors :: Int -> Int -> Int -> Int -> String -> Bool 
isFullOfColors red green yellow blue string 
    | (abs (red - green)) > 1 = False 
    | (abs (yellow - blue)) > 1 = False 
    | (string == []) = if (red /= yellow) || (green /= blue) then True else False 
    | (head string == 'R') = isFullOfColors (red + 1) green yellow blue (tail string) 
    | (head string == 'G') = isFullOfColors red (green + 1) yellow blue (tail string) 
    | (head string == 'Y') = isFullOfColors red green (yellow + 1) blue (tail string) 
    | (head string == 'B') = isFullOfColors red green yellow (blue + 1) (tail string) 

Но он не на входе "RYBG", возвращая False вместо True.

Что я делаю неправильно?

+1

Линия, которая решает, если строка заполнена цветами ('string == []) = if ...' reads (на английском языке) "return True, если нет одинакового количества красных и желтых шаров или нет одинакового количества зеленых и синих шаров ». Это не то же самое, что спецификация. –

+1

разделите свое решение на его части (сделайте предикаты для каждой из вышеперечисленных точек) и проверьте ввод на каждый;) – Carsten

+0

@ C.Quilley Я этого не видел. Благодаря! –

ответ

3

Кроме комментариев C. Quilley, вот несколько общих советов и предложение по структурированию вашей функции по-разному. Охранник string == [] лучше писать как null string, так как встроенная функция null примет это решение с одним совпадением шаблонов, вместо того, чтобы полагаться на список сопоставимых элементов (что происходит только тогда, когда элементы самого списка сопоставимы). Образец if ... then True else False можно укоротить до ..., так как это уже логическое значение с таким же значением. Как правило, попробуйте использовать соответствующий шаблон!

Я не вижу, где вы делаете (red /= yellow) || (green /= blue). Когда количество красных шаров и желтых шаров имеет общие ограничения?

Вместо строки, вы можете создать тип данных, который отражает шары:

data Ball = Red | Green | Yellow | Blue 
      deriving Eq 

Вы можете их отображаться точно так же, как и раньше:

instance Show Ball where 
    show Red = "R" 
    show Green = "G" 
    show Yellow = "Y" 
    show Blue = "B" 

И ты может захотеть встроить вспомогательную функцию в основную функцию:

isFullOfColors :: [Ball] -> Bool 
isFullOfColors = go (0, 0, 0, 0) 
    where 
    go :: (Int, Int, Int, Int) -> [Ball] -> Bool 
    go (r,g,y,b) (Red:balls) = ... 
    go (r,g,y,b) (Green:balls) = ... 
    go (r,g,y,b) (Yellow:balls) = ... 
    go (r,g,y,b) (Blue:balls) = ... 
    go (r,g,y,b) [] = ... 

Что касается намеков на логический параметр t: Они могут быть выражены как сравнения между r, g, y и b в сочетании с рекурсивными вызовами до balls.

Смежные вопросы