發表文章

目前顯示的是有「APL語言」標籤的文章

APL Code Golfing

圖片
APL實在是code golfing的利器。 今日突然想練一練code golf,馬上到 code-golf.io 看看,見到一道列印首二十行 Pascal Triangle 的題目,而排行第一的挑戰者居然使用了52個字元的答案。直覺告訴我APL應該可以更精煉,於是決定試試挑戰。 先公佈我的題解,只需要26個字元: 題目比預期中難,用了差不多半個小時仍然處理不好base case,即單一元素的陣列{1}。按下面來自維基的示範,當輸入為陣列V = {1, 3, 3, 1},應先將第1、2個元素相加並得出新元素1 + 3 = 4,如是者再重複相加第2、3及3、4個元素,得出新元素3 + 3 = 6與3 + 1 = 4: (圖片鏈結自 維基百科 ) 於是問題便轉化為產生陣列{1, 3, 3, 1}的指標的二元組(2-tuple) {1, 2},{2, 3},{3, 4}。用以存取陣列V的元素,並相加起來: 再費一些功夫抽取對角線上的元素{4, 6, 4}便可以了,感覺好像快將完成解答。 幾個想法突然湧現: 這樣的程式碼只是將程序式編程(procedural programming)的思維照搬不誤 程式碼極為欠缺美感,且勢必多於52個字元 致命的是,當陣列V為{1}的時候,會引致錯誤 原因係當V為{1}時, ⍴(¯1↓⍳⍴V) (1↓⍳⍴V) 的外積(outer product)是空的二維陣列,導致匿名函數  {+/V[⍺ ⍵]} 發生錯誤。縱使以常理推斷,陣列中沒有任何元素的時候,前述的函數應該不會被呼叫才對。例如python之中將必然拋出錯誤的lambda用於空陣列上: 再仔細思考,輸入陣列{1, 3, 3, 1}時只需要將輸入去掉頭、尾 (即{1, 3, 3}與{3, 3, 1})相加便可得出{4, 6, 4},再無條件地將{1}置於{4, 6, 4}的頭、尾,就可以得出Pascal Triangle的第五行{1, 4, 6, 4, 1}。 直觀地翻譯為APL,就得出題解使用的 匿名函數  {1,⍨1,(¯1↓⍵)+1↓⎕←⍵} ,最重要係當輸入為純量1或者陣列{1}時,輸出都會係{1, 1}。 不太理解為何其他參與者不用 J語言...

Dyalog APL比賽-2019年-Phase 1-第2題

圖片
先看看題目要求: 這是相對容易的一條題目吧,以下用 NARS2000 解題。 題目要求寫一個函數Z,當Z被輸入引數 N(0至100)的時候,傳回相對應的字母評級,就好似小學生的考試評級一樣。 思路非常簡單:建立字母陣列V,V 由65個F(0分至64分)、5個D(65分至69分)、10個 C(依此類推)、10個B及11個A順序組成;然後用N做陣列V的指數,返回V[N+1]的值。用圖像表示: 提交的程式碼如下: 解說一下: 表達式 (65 5 10 10 11)/'FDCBA' 用 replicate 函數 " /"  建構陣列 V 於是陣列 V  由65個  F ,5個  D ,10個  C ,10個  B ,11個  A  組成 基於右引數 ⍵ ,提取V的第 ⍵+1 個元素(何以?因為 Z 0 要傳回 V 的第 1 個元素,而 Z 100 則需要傳回V的第 101 個元素,如此類推) 注意,這個寫法容許 ⍵ 係 陣列 ,也是題目的要求。例如: APL 的簡潔總是給人一種不能言喻的美感。 一項更正: 原文介紹 " / " 時把它稱作運算子,但在以上用法中,其作用應為函數。

用APL產生六合彩組合

圖片
姑且用生成六合彩投注號碼做第一個例子,感覺應該比較有趣和生活化。 説穿了就是要從1至49“隨機”挑選6個數字,實在簡單到不行。這裡使用 NARS2000 直譯器,安裝過程就省略了,打開後,輸入  6?49 到唯一一個看似Notepad的視窗中: 之後按 Enter,結果將會在下一行顯示: 實再言簡意賅到不得了。  6?49 的意思就是從1至49中抽取6個不同的元素。在此,  ? 係一個 函數 ,其左右兩邊各自有數字 引數   6 和  49 。由於 ? 使用左右引數,這稱之爲 ? 函數的 雙價 用法。所返回的是有6個元素的 陣列 。 既然有雙價就勢必有 單價 吧?不錯, 單價 使用下, ? 返回 1至49内的一個數字 純量 : 關於 純量 與 陣列 的區別與用法,往後會再探討。 另外,將左引數換成49的話,所得就是1至49的隨機排列 (permutation) 了: 試想想,以上功能如果用 Java / C / Python 編寫的話要如何處理?