ランダムHaskellコードチャレンジ


私の友人と同僚が私に面白いミームを見せたとき、私は仕事にいました、そして、それは単純なプログラミング挑戦または多分テストで先生を騙した学生についてです.学生からの要求された出力は、プログラムをつくって、スクリーンに次の結果を生じることになっている
ABCDEFGFEDCBA
ABCDEF_FEDCBA
ABCDE___EDCBA
ABCD_____DCBA
ABC_______CBA
AB_________BA
A___________A
まず,ループのアルゴリズムとループ内のデータの操作/再配置により,所望の結果を達成することが課題となる.学生は、2つの入れ子にされたループといくつかのインデックス操作を持っているダミーの非働くコードを提示しました.これらのループは死んだコードであるように見えます、そして、学生はそれからコード化された出力を印刷する手順を加えます.その後、教師は、基礎となるロジックをチェックして、学生にコードを直接走らせるように頼まなかったが、学生は管理されたコードを明白な目で隠すことができました.
for(int i=0; i<arr.length; i++) {
  for(int j=0; i... ) {
    // some none working code..
  }
}
printsomething()

printSomething() {

  print("ABCDEFGFEDCBA")
  print("ABCD....")
  ...
}
それは非常におもしろいです、そして、それは非常に挑戦的です、そして、私はおそらく「Haskellコードでこの種の挑戦を解決しない理由」と思いました.
問題定義がなければ、私たちは「A」を「G」に印刷する必要があると仮定します、そして、その後、それは「F」から「A」まで戻るでしょう.その後、すべての次の行のためにこの規則を適用することができます、そして、ちょうど追加されたねじれだけで、我々はまた、1つのキャラクタが印刷するために残っているまで、真ん中のキャラクタを除去します.

最初のステップ:データを生成する


リストのリストを生成する
長さ7のリスト1
長さ6のリスト2
長さ5のリスト3
...
それから、我々はリストにこれを置きます
[ list1, list2, list3, ... ]
今のところこのリストは、1でインクリメントされた順序番号が含まれています、我々はHaskell無限リストでそれを達成し、希望の長さだけを取る.
take 5 [1..] -- take 5 elements in an infinite list.
-- [1, 2, 3, 4, 5]
さて、これまでのところ、1によってインクリメントされる数字のリストを構築する機能があります.次に、行として使用される長さ7のリストを生成します.この場合、リストを長さとして生成するためにマップされます.
import Data.List

rangeMatrix = fmap (\n -> take n [1..]) [1..7]
-- [ [1]
-- , [1, 2]
-- , [1, 2, 3]
-- , [1, ... ]
-- ...
-- ]
The fmap 以下はJavaScriptのようなものですArray.map , Mapper関数を使用してリスト内の各要素をマップします.この場合、マッピング関数は整数(n)を受け取り、(n)要素のみを取るリストを返します.
現在、私たちは数の生成された行列を持っています、我々はこれらの数字を我々の望ましい文字「A」に「G」に変えます
conv :: Int -> Char
conv 1 = 'A'
conv 2 = 'B'
conv 3 = 'C'
conv 4 = 'D'
conv 5 = 'E'
conv 6 = 'F'
conv 7 = 'G'
conv _ = ' '
次に、RangeMatrix数値を変換文字にマップします.
rangeMatrixChars :: [[Int]] -> [[Char]]
rangeMatrixChars xss = fmap (fmap conv) xss
-- [ ['A']
-- , ['A', 'B']
-- , ['A', 'B', 'C']
-- , ['A', ... ]
-- ...
-- ]

第2ステップ:フォーマットデータ


次のステップと最も興味深い部分は読み込み可能な文字列にこのマトリックスをフォーマットすることです.モジュラ機能を設計するための機能的プログラミングにおける一般的な慣習である.私たちのケースでは、我々は現在、データを生成する関数を設計し、今我々の行列文字を受け入れると、文字の単一のリストに処理する関数を作成するString Haskellで).
prettyFormat :: [[Char]] -> [Char]
prettyFormat xss =
 foldl prettyFormatStep [] xss
そして、フォーマットの各ステップは
prettyFormatStep :: Int -> [Char] -> [Char] -> [Char]
prettyFormatStep maxChar [] xs =
  xs
prettyFormatStep maxChar acc xs =
  xs
  ++ ['\n']
  ++ acc
ABCDEFG
ABCDEF
ABCDE
ABCD
ABC
AB
A
目的の出力に近づきます.また、少し微調整する必要があります.次に、消えるキャラクタを示すために、否定的なスペースを加えます.今のところ、我々は* 人物
negativeSpaceFormat maxChar whiteSpaceChar xs = 
  replicate (abs (length xs - maxChar)) whiteSpaceChar
prettyFormatStep
prettyFormatStep maxChar [] xs =
  xs
+ ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)

prettyFormatStep maxChar acc xs =
  xs
+ ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)
  ++ ['\n']
  ++ acc
ABCDEFG
ABCDEF*
ABCDE**
ABCD***
ABC****
AB*****
A******
そして最後に、1行あたりの出力のミラーを追加します.
prettyFormatStep maxChar [] xs =
  xs
  ++ negativeSpaceFormat maxChar '*' xs
+ ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)

prettyFormatStep maxChar acc xs =
  xs
  ++ negativeSpaceFormat maxChar '*' xs
+ ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)
  ++ ['\n']
  ++ acc
負の空白文字が対称であるので、我々はそれを逆にする必要はありません、しかし、一般に、逆もまた適用されます.最終出力は
ABCDEFGGFEDCBA
ABCDEF**FEDCBA
ABCDE****EDCBA
ABCD******DCBA
ABC********CBA
AB**********BA
A************A
でも待って!私たちにはエラーがあります、これまでの出力はこの記事の初めの予想された出力と同じでありません.最初の行が重複していることに気づくならG 番目の列には余分な* 行ごとに.問題は、リストの正確な逆のデータを正確に反映していることです.我々は、反転リストの最初の要素を削除することによってこれを修正することができます.我々は、関数を使用することができますtail これを修正するには
prettyFormatStep maxChar [] xs =
  xs
  ++ negativeSpaceFormat maxChar '*' xs
- ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)
+ ++ tail (negativeSpaceFormat maxChar '*' xs ++ reverse xs)

prettyFormatStep maxChar acc xs =
  xs
  ++ negativeSpaceFormat maxChar '*' xs
- ++ (negativeSpaceFormat maxChar '*' xs ++ reverse xs)
+ ++ tail (negativeSpaceFormat maxChar '*' xs ++ reverse xs)
  ++ ['\n']
  ++ acc
ABCDEFGFEDCBA
ABCDEF*FEDCBA
ABCDE***EDCBA
ABCD*****DCBA
ABC*******CBA
AB*********BA
A***********A
あなたがこの点まで記事を読むならば、あなたは拍手に値します👏 我々は予想される出力に着いた.
いくつかの最適化と構文を調整する必要があります、いくつかのHaskellのより良い理解を持っている可能性がありますetaの削減、リストの理解、および多くを指摘することがあります.この解決策についてあなたに任せます.
ありがとう、そして楽しいコーディング
完全な実行可能なソースコード:https://replit.com/@RonnelReposo/SimplisticAffectionatePackagedsoftware#Main.hs