2016-04-07 10 views
1

Haskell'e yeni tanıştım ve type Img = [String] olarak gösterilen görüntülerle çalışıyorum. Görüntüyü 1 veya daha fazla satır yukarı veya aşağı hareket ettiren bir işlev oluşturmak istiyorum.Haskell: Bir görüntü için bir rulo işlevi tanımlamak

Aşağıdaki örnek resim.

img 1= [ "XX XX"   
     , " X " 
     , "XX XX" 
     ]  

Amacım üzerinde sarma, dikey görüntüyü çeviren bir fonksiyon moveImg :: Int -> Img -> Img yazmaktır; ör .:

moveImg 1 (img 1) = -- Move up by 1 
    [ " X " 
    , "XX XX" 
    , "XX XX"   
    ] 

moveImg (-1) (img 1) = -- Move down by 1 
    [ "XX XX" 
    , "XX XX"  
    , " X " 
    ] 
+2

Eğer şimdiye kadar denedim neyi gösterebilir olabilir? – duffn

+0

@duffn - Bu problemle ilgili bazı problemleri bilen bir arkadaşla çalıştım. O ----------- hareket n olarak = kafa ts ile geldi: (hs ++ kuyruk ts) Burada (hs, ts) = splitAt n ---------- ama onun işe yaramasını istemediğim sessiz değil. – evian1

+2

Nasıl çalışmasını istersiniz? – Carsten

cevap

1

belki daha basit bir yaklaşım

moveImg n xs = take len $ drop (mod n len) $ cycle xs 
     where len = length xs 
+3

Eminim ki bunu kopyalayıp yapıştıracak ve burada yatay olarak yapılması gereken başka bir sorunla geri dönecek ... [OH BEKLEME] (https://stackoverflow.com/questions/36499786/haskell)-görüntü-on-yatay-line -moving. –

+0

Haklı olduğunuzda haklısınız. – karakfa

2

o modülo operatörü eksik çünkü sen arkadaşının kod çalışmıyor - yani rotasyon etrafında "sarma" değildir. Carsten'in kodu çalışır (onun kodu, listeyi kendi başına istifleyerek ve sonra uygun dilimi alarak çalışır; yığıldığı için "sarılır"); İşte bir alternatif. Bu sadece the array rotation problem.

import Data.List (splitAt) 
    import Data.Tuple (swap) 



    rotate :: Int -> [a] -> [a] 

    rotate k xs = uncurry (++) $ swap $ splitAt (k `mod` length xs) xs 

Biz ikiye liste bölünmüş - ve mod rotasyonu, swap sırt için ön etkinleştirmek ve bunları birbirine eklemek için. swap, tuple üzerinde çalışır ( splitAt döndürür). uncurry, yalnızca iki ayrı bağımsız değişken yerine bir dizi üzerinde çalışacak şekilde liste birleştirmeyi ( ++) zorlar. a -> b -> c türünün bir işlevini (a, b) -> c türüne dönüştürür.

Bazı testler-- forM_, her satırı sırayla basmak için bir for döngüsü gibi kullanılır.

import Control.Monad (forM_) 
    main = do 
     let img = ["XX XX",   
       " X ", 
       "XX XX"]  
     putStrLn "Up is positive" 
     forM_ (rotate 1 img) print 
     putStrLn "Down is negative" 
     forM_ (rotate (-1) img) print 

şu çıktıyı verir: sen, pozitif/negatif değerler kullanmak yerine bir Up/Down veri türünü yaratabilir istiyorsa

Up is positive 
    " X " 
    "XX XX" 
    "XX XX" 
    Down is negative 
    "XX XX" 
    "XX XX" 
    " X " 

. Örneğin.

data Direction = Up | Down 
    rotate :: Direction -> Int -> [String] -> [String] 
    rotate d k xs = . . .