Python Challenge を Squeak システムの Smalltalk 言語で

Python Challenge は、出題ページの情報(含む、ソース)をヒントにして、続く次の出題ページの URL を導き出すクイズ集。もちろん Python を駆使することが前提ですが、ふだん使い慣れた別の言語処理系でチャレンジしておられるかたも多いようです。そこで、解答を得るためのスクリプトSqueakSmalltalk を用いてみました。とりあえずレベル 10 まで。以下、ネタバレ要注意。

レベル 0

2 raisedTo: 38

レベル 1

'koe' collect: [: each | 
   each isLetter 
      ifTrue: [Character alphabet atWrap: (Character alphabet indexOf: each) + 2] 
      ifFalse: [each]]

レベル 2

contents comment bag rares
contents _ (HTTPSocket httpGet: 'http://www.pythonchallenge.com/pc/def/xyz.html') contents. comment _ (contents findBetweenSubStrs: #('<!--' '-->')) inject: '' into: [: result : each | result size < each size ifTrue: [each] ifFalse: [result]]. bag _ comment asBag. rares _ bag select: [: each | (bag occurrencesOf: each) = 1]. ^ comment select: [: each | rares includes: each]

手抜き版

contents comment
contents _ (HTTPSocket httpGet: 'http://www.pythonchallenge.com/pc/def/xyz.html') contents. comment _ (contents findBetweenSubStrs: #('<!--' '-->')) inject: '' into: [: result : each | result size < each size ifTrue: [each] ifFalse: [result]]. ^ comment select: [: each | each isLetter]

レベル 3

contents comment
contents _ (HTTPSocket httpGet: 'http://www.pythonchallenge.com/pc/def/xyz.html') contents. comment _ (contents findBetweenSubStrs: #('<!--' '-->')) inject: '' into: [: result : each | result size < each size ifTrue: [each] ifFalse: [result]]. (((1 to: comment size - 8) collect: [: idx | | subCollection | { subCollection _ (comment copyFrom: idx to: idx + 8) asOrderedCollection. #(1 4 7) collect: [: nn | subCollection removeAt: nn]}] thenSelect: [: each | (each first allSatisfy: [: char | char isUppercase]) and: [each last allSatisfy: [: char | char isLowercase]]]) collect: [: each | each last middle]) as: String

レベル 4

nString prevString contents
nString _ '12345'. World findATranscript: nil. [ contents _ (HTTPSocket httpGet: 'http://www.pythonchallenge.com/pc/def/xyz.php?nothing=', nString) contents. contents _ contents asUnHtml withoutTrailingBlanks. Transcript cr; show: contents. prevString _ nString. nString _ contents subStrings last. (contents findString: 'Divide by two') isZero ifFalse: [nString _ (prevString asNumber // 2) asString]. nString asInteger isNil ifTrue: [^ contents]] repeat

レベル 5

Python のライブラリを使わなければならないのでここでギブアップか…と思ったのですが、この問題を解くために、もとのモジュールのサブセットに相当するスクリプトRuby で書いてくださったかたがおられましたので、これを参考に同様のことを SqueakSmalltalk で記述しました。オリジナルの Python モジュールや Ruby のコードではクラスを定義しているのですが、その必要もなさそうなので解答の出力を含めた手続き的なものにしました。

参考:
http://d.hatena.ne.jp/teamikl/20050508#p1
/lib/pickle.py

stream mark buffer result char bracketing
stream _ CrLfFileStream fileNamed: 'xyz.p'. mark _ OrderedCollection new. buffer _ Dictionary new. result _ OrderedCollection new. bracketing _ [| lastMark | lastMark _ result at: (result lastIndexOf: mark). [result last = lastMark] whileFalse: [lastMark addFirst: result removeLast]]. [char _ stream next. stream atEnd] whileFalse: [ char caseOf: { [$I] -> [result add: stream nextLine asInteger]. [$S] -> [result add: (Compiler evaluate: stream nextLine)]. [$(] -> [result add: mark copy]. [$t] -> [bracketing value]. [$l] -> [bracketing value]. [$a] -> [| value | value _ result removeLast. result last add: value]. [$p] -> [buffer at: stream nextLine asInteger put: result last]. [$g] -> [result add: (buffer at: stream nextLine asInteger)]. [$.] -> [stream upToEnd]}]. World findATranscript: nil. result first do: [: lines | lines do: [: line | line last timesRepeat: [Transcript show: line first]]] separatedBy: [Transcript cr]. ((SystemWindow windowsIn: World satisfying: [: window | window isActive]) anyOne submorphs select: [: morph | morph isKindOf: PluggableTextMorph]) anyOne font: (TextStyle named: 'Atlanta') defaultFont

レベル 6

nString members repeat contents archive
nString _ '90052'. archive _ ZipArchive new readFrom: (FileStream fileNamed: 'xyz.zip'). members _ archive members. World findATranscript: nil. repeat _ true. [repeat] whileTrue: [ | fileName member | fileName _ nString, '.txt'. contents _ ((FileDirectory default directoryNamed: 'xyz') fileNamed: fileName) contents. contents _ contents asUnHtml withoutTrailingBlanks. member _ (members select: [: mm | mm fileName = fileName]) anyOne. Transcript show: member fileComment withSqueakLineEndings. nString _ contents subStrings last. nString asInteger isNil ifTrue: [repeat _ false]]. archive close. ((SystemWindow windowsIn: World satisfying: [: window | window isActive]) anyOne submorphs select: [: morph | morph isKindOf: PluggableTextMorph]) anyOne font: (TextStyle named: 'Atlanta') defaultFont

レベル 7

form xx gray firstLevelCode firstLevel secondLevelCode secondLevel codeToString
form _ PNGReadWriter formFromStream: ( HTTPSocket httpGet: 'http://www.pythonchallenge.com/pc/def/xyz.png' accept: 'image/png'). form asMorph openInWorld. firstLevelCode _ OrderedCollection new. xx _ 0. [(gray _ form colorAt: xx @ 50) isGray] whileTrue: [ firstLevelCode add: (gray red * 255) rounded. xx _ xx + 7]. codeToString _ [: grys | String withAll: (grys collect: [: each | each asCharacter])]. firstLevel _ codeToString value: firstLevelCode. secondLevelCode _ ((firstLevel findBetweenSubStrs: #('[' ']')) last subStrings: #($,)) collect: [: each | each asInteger]. secondLevel _ codeToString value: secondLevelCode. ^ {firstLevel. secondLevel}

レベル 8

残念ながら Squeak システムには bzip2 の移植がまだないのでパス。

レベル 9

pen first second
first _ #(100 100 100 200 200 200 200 100 100 100). second _ #(150 150 150 250 250 250 250 150 150 150). pen _ Pen new defaultNib: 2. Display fillWhite; restoreAfter: [ pen color: Color brown ; place: first first @ first second. first pairsDo: [: xx : yy | pen goto: xx @ yy]. pen color: Color darkGray; place: second first @ second second. second pairsDo: [: xx : yy | pen goto: xx @ yy]]

レベル 10

aa
aa _ [: nn | | value rule | value _ '1'. rule _ [: curr | | next | next _ OrderedCollection new: curr size + 1. (RunArray newFrom: curr) runsAndValuesDo: [: run : val | next add: run asString asCharacter; add: val]. next as: String]. nn timesRepeat: [value _ rule value: value]. value]. ^ (aa value: 30) size