トップ «前の日記(2010-05-28) 最新 次の日記(2010-05-30)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2010-05-29

_ 昨日の続き

nobsunが解答例を作ってくれたので眺めてみる(入力するところは後から付けた)。

import IO
 
type Rect  = (Int,Int)
type Rects = [Rect]
 
maxRectArea :: [[Int]] -> Int
maxRectArea = maximum . map (uncurry (*)) . concatMap concat . rects
 
rects :: [[Int]] -> [[Rects]]
rects = tail . scanl (zipWith v) (repeat []) . map (scanl1 h)
 
h :: Int -> Int -> Int
_ `h` 0 = 0
n `h` _ = n+1
 
v :: Rects -> Int -> Rects
_  `v` 0 = []
[] `v` n = [(n,1)]
ps `v` n = case span ((n <=) . fst) ps of
  ([],_)  -> (n,1) : map yinc ps
  (qs,rs) -> (n,1+snd (last qs)) : map yinc rs
 
yinc :: (Int,Int) -> (Int,Int)
yinc (x,y) = (x,y+1)
 
rLine :: IO [Int]
rLine = do
          lis <- getLine
          readIO $ "[" ++ lis ++ "]"
 
readLines :: Int -> IO [[Int]]
readLines 0 = return []
readLines n = do
          lis <- readLines (n - 1)
          putStrLn $ "input line " ++ (show n) ++ "..."
          llis <- rLine
          return $ llis:lis
 
main :: IO ()
main = do
          let size = 5
          lns <- readLines size
          putStrLn . show $ maxRectArea lns

当然のように、関数合成の.とかタプルを引数に取れるようにカリー化関数を変えるuncurryとか出て来るが、まあ読める。

しかし垂直の加算の箇所(vではなく、tail . sncal (zipWith v)のあたり)は難しいな。多分、しばらくはこういう書き方もできなさそうだ。

これは面白い感覚だ。

それでなんで難しいと感じるのか、考えてみた。どうもzipWithが問題らしい。引数が3個でかつ関数が引数に入ると途端に難しく感じているようだ。

人によって学習方法はいろいろある。どうしていろいろになるかと言えば、個人的な特性か、または習慣として身についた学習方法のどちらかになると思う。

たとえば語学の天才ってのが歴史の本に出てくることがある。最初にどこかの外国語を覚えようと考えると、1週間くらい、その言語の辞書を頭から丸暗記して、1週間後には完全な読み書きができるようになる。

普通の人はそうはいかないから、最初は単純な文法と少ない語彙で表現を入出力することから始めて、徐々に構文と語彙を増やしていく。

この場合、記憶力(単に覚えるだけではなく例文とかを覚えるのだろうと想像する)の特性が、語学の天才の学習方法を普通の人と分けているところだろう。

おれは記憶力がほとんどないから(ここでは短期的にそれぞれ独立した多数のことを覚える能力のこと)、概念を最初に掴んでそれを利用して構造を作り、あとからその構造の部分部分に記憶すべきことを当てはめていくという学習方法を取ることが多い。記憶は関連があるとしやすいというのは、おそらく普遍的真実だから「いい国作ろう鎌倉幕府」とかやって数字を覚えるのだ。

たとえば中学とか高校の数学では、公理と本当に基本的な定理しか覚えられないから、それだけを使って証明する。必要性として速度的にその方法では間に合わなくなったときになって、便利な(応用的な)定理をその長い証明の部分部分に対して当てはめていくことで(もちろん順序としては逆で、この部分はおそらく定理があるはずである、と考えてから定理集から適合するものを見つけて来ることになる)、記憶していくことができる。

すると、おれがリファクタリングが好きなことに説明がつく。

最初はまず冗長なものを作り、しかしこのような操作をする便利なものがあるはずだ、と調べて見つけてそれを当てはめるという順番だ。

おそらくその過程で記憶することができるのだ。考えてみればRubyのmapだのinjectだのもそういった過程を踏んで使えるようになったのであった。

おれの学習過程というのは、そのような段階を踏むことが多いので、そこからマニュアル教育とか車輪の再発明先生とかに対して、非常な嫌悪感が生じるようだ。というのは、それでは学習できないからだな。

もし、おれのそのような学習過程がそれなりの普遍性を持つのであれば、「初心者ですけど難解です」君に向学心がなければ、そりゃ確かに基本語彙からちょっとでも外れたものが出てくれば、それは難解だろうし、その時点の基本語彙より組み合わせが多少複雑になればなおさらで、しかも向学心がないのだから未来永劫どうやっても難解だろう。

ということに気づけたというか思い出したのは、ある点でよかった。やはり時々は初心者に返って初心を思い出すのは良いことだな。


2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|

ジェズイットを見習え