Codeforces 110B - B. Lucky String
calc :: Int -> String calc n = take n $ cycle "abcd" main = do s <- getLine putStrLn $ calc $ read s
Processing, プロジェクト名と同じ名前のクラスは定義できない。
プロジェクト名(.pdeファイル名)と同じ名前のクラスを定義しようとすると、以下のエラーメッセージが表示されました。
The nested type Test cannot hide an enclosing type
Processingで正三角形を描画する
Processingで正三角形を描画しようと思い、コードを書き始めたけど、すぐに手が止まってしまった。triangle()を使って、3点の座標位置を指定すれば三角形を描画できる。だけど、3点の座標位置はどう決めたら良いのだろうか?
そもそも正三角形とはどういう形をしているのか。Wikipediaには次のように書いてある。
正三角形(せいさんかくけい、英: equilateral triangle)は、正多角形である三角形である。つまり、3本の辺の長さが全て等しい三角形である。3つの内角の大きさが全て等しい三角形と定義してもよい。1つの内角は 60°(π/3 rad)である。また一つの内角が60°である二等辺三角形は正三角形となる。
正三角形 - Wikipedia
3本の辺の長さが等しい、3つの内角の大きさが全て等しい、1つの内角は60°ということは理解していた。では、そこから正三角形の3点の座標位置はどうなると言えるのか。上のページを読み進めると、正三角形の高さは、辺の長さをaとすると、a*sqrt(3)/2 となると書かれてある。つまり、高さは整数にはならない。
さらにページを読み進めると、正三角形の3点の座標位置の求め方も書いてある。これを使えば3点の位置も求めることが出来るけれど、なぜそのような値になるのか考えてみた。正三角形に何本かの補助線を引いてみると、意外に簡単に計算できた。
上図の正三角形の内部にみえる小さな三角形は全て、それぞれ内角が30°、60°、90°の直角三角形になっている。b, c, dの値はそれぞれ次のようになる。
b = a/2 * sin60° c = a/2 * cos60° d = c * tan30°
点Aの座標は、(x, y-(b+d))となる(y座標は下向きを正としている)。点Bと点Cの座標は、点の回転公式より求めた。
(x, y)を原点のまわりに角aだけ回転して(x', y')に移されるとき、 x' = x*cos(a) - y*sin(a) y' = x*sin(a) + y*cos(a)
Processingプログラム:
// -*- mode: java -*- class EqTriangle { // equilateral triangle float x, y, n; public EqTriangle(int x, int y, int n) { this.x = x; this.y = y; this.n = n; } public void draw(int angle) { float b = this.n * sqrt(3) / 4.0; float c = this.n / 4.0; float d = c * tan(radians(30)); float x1 = 0; float y1 = -(b + d); float r = radians(120); float x2 = x1*cos(r) - y1*sin(r); float y2 = x1*sin(r) + y1*cos(r); float x3 = x1*cos(r*2) - y1*sin(r*2); float y3 = x1*sin(r*2) + y1*cos(r*2); pushMatrix(); translate(this.x, this.y); rotate(radians(angle)); triangle(x1, y1, x2, y2, x3, y3); popMatrix(); } } EqTriangle t1, t2, t3; void setup() { size(400, 400); t1 = new EqTriangle(width/2, height/2, 60); t2 = new EqTriangle(width/2, height/2, 100); t3 = new EqTriangle(width/2, height/2, 140); } void draw() { background(255); noFill(); t1.draw(frameCount); t2.draw(-frameCount); t3.draw(frameCount); }
実行すると、以下のように正三角形がくるくると回転します。
primesパッケージをインストール
primesパッケージをインストールします。
cabal install primes
Prelude Data.Numbers.Primes> take 30 primes [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113] Prelude Data.Numbers.Primes> primes !! 0 2 Prelude Data.Numbers.Primes> primes !! 9999 104729 Prelude Data.Numbers.Primes> primeFactors 1234567 [127,9721] Prelude Data.Numbers.Primes> primeFactors 12345 [3,5,823] Prelude Data.Numbers.Primes> filter isPrime [1..100] [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97]
Project Eulerの問題を解くときに使ってみよう。
参考:
Codeforces 37A - A. Towers
import Data.List calc :: [Int] -> (Int, Int) calc xs = (maximum [count x xs | x <- xs], length $ nub xs) where count a xs = sum [1 | x <- xs, x == a] main = do s <- getLine t <- getLine let (x, y) = calc $ map read $ words t putStrLn (show x ++ " " ++ show y)
個数を求めるのに、1 からなるリストを sum するのはどうも好きになれない。他に良い方法はないだろうか。
Codeforces 122B - B. Lucky Substring
calc :: String -> Int calc s | n4+n7 == 0 = -1 | otherwise = if n4 >= n7 then 4 else 7 where n4 = sum [1 | c <- s, c == '4'] n7 = sum [1 | c <- s, c == '7'] main = do s <- getLine print $ calc s
Codeforces 122A - A. Lucky Division
isLucky :: Int -> Bool isLucky n = show n == filter (\c -> c == '4' || c == '7') (show n) calc :: Int -> String calc n = if null [i | i <- [1..n], isLucky i, n `mod` i == 0] then "NO" else "YES" main = do s <- getLine putStrLn $ calc $ read s