代码挑战“ Vrolijke Framboos”事后验尸
星期二,我們在JDriven舉行了第二次“ Vrolijke Framboos”(快樂樹莓的荷蘭語)Java代碼挑戰賽 ,這是爆炸性的! 今年的挑戰是創建一個REST服務客戶端,該客戶端將與服務器一起玩猜數字游戲。 設置會話后,您會猜到一個數字,服務器將以“較低”,“較高”或“賓果”響應。 目標是在兩分鐘內猜出盡可能多的數字。 給定挑戰的名稱,您可能會猜到目標平臺將是Raspberry Pi !
這是一次令人難以置信的有趣體驗,在這篇文章中,我想解釋一下我是如何應對挑戰的,而我的解決方案最終是如何獲得第二名的,這讓我只是錯失了將獎杯和新樹莓帶回家的機會。
制備
從上一期挑戰中我所知道的(不幸的是,這并不是我的一部分),我們必須提供一個可運行的jar,該jar將在樹莓上執行。 我通過設置一個空的Maven項目來進行準備,該項目將其自身及其依賴項組裝到一個胖的jar中,該胖的jar可通過java -jar <jarfile> .jar從命令行運行。 我還包括了一堆我甚至沒有使用過的標準依賴項(Log4j,Junit,Guava)。
執行
當我們被解釋為將通過發布請求與REST服務進行通信時,我首先添加了Apache HTTP客戶端( 流暢的API很好!),并為該客戶端添加了Jackson。
我還使用了一個現有的Spring Boot REST測試項目來添加我自己的服務器模擬版本,因為直到截止日期前30分鐘我們才可以使用該服務器。 我花了相當多的時間來創建服務器端點,以便我的客戶可以和別人交談。
在服務器就位的情況下,我實現了客戶端接口。 使用Jackson + Apache HTTP客戶端,這非常簡單。 一個例子:
public GuessResponse guess(GuessRequest req) throws IOException {String result = Request.Post(baseUrl + "/api/numbergame").bodyString(toJson(req), ContentType.APPLICATION_JSON).execute().returnContent().asString();return mapper.readValue(result, GuessResponse.class); }這是進行猜測的REST調用; 非常簡單!
算法
該操作的“大腦”是一個Worker線程,該線程不斷啟動新游戲,并且在游戲內使用簡單的二進制搜索來盡快向下鉆取正確的猜測。 通過偽查詢中的二進制搜索來猜測數字是:
low_bounds = 0 high_bounds = 2^63 loop:pivot = low_bounts + (high_bounds - low_bounds / 2)guess = guess(pivot)if guess == "lower":high_bounds = pivot - 1else if guess == "higher":low_bounds = pivot + 1else if guess == "bingo"return pivotelsethrow Error典型的復雜度是O(log n),比O(n)蠻力好得多。
我的第一個實現使用2 ^ 31的上限,但是我很快發現服務器正在分發更高的數字。
最佳化
通過基本的實現工作,我開始嘗試優化解決方案,因為我想我不是唯一一個使用binsearch實現的人。 我的第一個猜測是通過讓多個工人同時玩游戲來并行化工作。 效果很好; 似乎最大的瓶頸是HTTP往返,轉移到8個線程使我大大提高了速度。
不幸的是,當截止日期臨近時,我聽說實際的比賽只能允許一個會話進行,所以我的方法行不通。 我花了很多時間試圖找到一種方法來讓多個線程處理該問題,以嘗試規避HTTP開銷,但是不幸的是,我沒有時間提出解決方案。
比賽時間
我們提交了解決方案(在20位左右的參賽者中,我們大約有13種實現方案),而我的同事Pepijn開始運行它們。 該服務器具有非常整潔的報告功能,可向我們實時顯示得分!
某些解決方案根本不起作用,但一堆卻不能,而且很快! 我進入前三名的機會確實開始變得渺茫了。 我的提交實際上是最后一次執行,因此必須等待,這真讓人不知所措。 當他們最終運行我的解決方案時,它比我期望的運行速度要快得多,這是基于我看到的運行自己的機器的速度。 這顯然是由于樹莓派和服務器之間的有線連接。
所有解決方案都運行了2分鐘,我以556個正確的猜測最終排名第二。 數字1(由里卡多提交)是714,數字3是289,所以我對結果非常滿意!
驗尸
這是一個了不起的夜晚,當我們接到任務后,看到每個人都進入極端聚焦模式真是太有趣了。 我們大多數人浪費很少的時間(如果有的話)吃披薩,而是非常努力地工作以找到可行的解決方案。
對我來說很好的是
- 準備 :必須擁有一個IDE,該IDE的一個空項目已經準備好構建到jar中。 進行這樣的設置不需要花費很多時間,但是當您的總時間約為2-3小時時,那15分鐘非常有價值!
- 算法 :我的二進制搜索方法效果很好,特別是與某些人采用的蠻力方法相比。 最初,我以為他們會使用整個“ int”搜索空間,但是我很快就知道這實際上是一個“ long”搜索空間。 蠻力根本不會削減它。
- 關注速度 :我沒有為單元測試或使用getter / setter創建適當的Java POJO而煩惱。 CheckStyle用我的代碼會心臟病發作。 重要的是使其正常運行。
- 刪除調試語句 :System.out非常昂貴! 有些人忘了刪除緊密循環中的打印內容,這會大大降低您的應用程序的速度。 我的只報告了猜測的數字。
本來可以更好的
- 準備 :盡管我設置了IDE,但我不知道我會實現模擬REST服務。 如果我可以使用Node.js之類的東西和基本的REST服務,那么我將在客戶端集成方面取得很大進步。
- 專注于多線程 :最終沒有成功的賭博。 會話系統將不允許執行并行游戲,并且二進制搜索實際上并不能很好地并行化。
- 缺乏對搜索空間的關注 :我認為0到2 ^ 63之間的完整空間是可以猜測的,但是很明顯,當我們開始比賽時,它總是在猜測非常高的數字。 如果我創建了第一個測試結果的直方圖,我可能會發現分布根本不均勻。 我本可以使下限和上限適應所找到的數字。
- 缺乏對HTTP開銷的關注 :我沒有時間去尋找如何通過例如保持連接打開來減少HTTP開銷的方法。 回想起來,這可能會有很大的不同。
結論
這是我的第一個代碼的質詢/ hackaton我參加了,這是這么多的樂趣,我可以把它推薦給任何人。 在競爭激烈的環境中編碼與您的日常工作有很大不同。 這要更加激烈,因此每個人都直接進入“區域”,而實際上您的生產力非常高。 這個“區域”對我來說是個快樂的地方,相當讓人上癮。 缺點是我被大肆宣傳,甚至無法入睡。 我寫這篇文章的主要原因是 把它從我的腦子里弄出來;)
翻譯自: https://www.javacodegeeks.com/2015/07/code-challenge-vrolijke-framboos-postmortem.html
總結
以上是生活随笔為你收集整理的代码挑战“ Vrolijke Framboos”事后验尸的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: akka2.5_播放2.0:Akka,R
- 下一篇: OPPO手机拍照没有声音怎么办