GoST@'New Year''s Day'

例年の如くさださんを拝みつつ進捗公開。

!Object methodsFor: 'golf'!
doesNotUnderstand: m
  | a s k |
  a := m arguments size.
  s := m selector, '*' copyReplaceAll: ':' with: '*:'.
  k := {m selector. self class}.
  ^m selector: (GolfDic at: k ifAbsentPut: [
    self class allSelectors asSortedCollection detect:
      [:x| (x occurrencesOf: $:) = a and:
        [ s match: x ignoreCase: false ] ] ]); sendTo: self!
H
  ^'Hello, world!' displayNl!
H: args
  ^('%1ello, %2orld%3' bindWithArguments: args) displayNl!
Q
  | s |
  s := thisContext.
  [ s methodClass = UndefinedObject ] whileFalse: [ s := s sender ].
  ^(s method methodSourceString, '!') display!
P
  ^self displayNl!
P: f
  ^self displayOn: f!
G
  ^GolfDic!

!Symbol methodsFor: 'golf'!
doesNotUnderstand: m
  ^m sendTo: (self C ifNil:[ ^super doesNotUnderstand: m ])!

!Character methodsFor: 'golf'!
doesNotUnderstand: m
  ^m sendTo: (PseudoGlobal at: self ifAbsent: [ ^super doesNotUnderstand: m ])!

!CharacterArray methodsFor: 'golf'!
C
  | s |
  s := self, '*'.
  ^Smalltalk at: (##(Smalltalk keys asSortedCollection)
    detect: [:k| s match: k ignoreCase: false ]
    ifNone: [ ^nil ])!
E
  ^Behavior evaluate: self!
%% a
  ^self bindWithArguments: a!
/ p
  ^p isInteger ifTrue: [ super / p ] ifFalse: [ self tokenize: p ]!

!Number methodsFor: 'golf'!
doesNotUnderstand: m
  ^m sendTo: (1 to: self)!
~ n
  ^n < self
    ifTrue:  [ self to: n by: -1 ]
    ifFalse: [ self to: n ]!
? n
  ^self raisedTo: n!

!Integer methodsFor: 'golf'!
>> n
  ^self bitShift: n negated!
<< n
  ^self bitShift: n!
& n
  ^self bitAnd: n!
| n
  ^self bitOr:  n!
\ n
  ^self bitXor: n!

!Boolean methodsFor: 'golf'!
&& b
 ^self and: b!
|| b
 ^self or:  b!
T: t F: f
 ^self ifTrue: t ifFalse: f!

!Collection methodsFor: 'golf'!
R
  ^self asArray at: Random next * self size // 1 + 1!
D
  ^self asArray inject: Dictionary new into: [ :d :a | d add: a. d ]!
@ o
  ^(o respondsTo: #collect:)
    ifTrue:  [ self class withAll: (o collect: [:i| self at: i ]) ]
    ifFalse: [ self at: o ]!
* o
  ^(o respondsTo: #,)
    ifTrue:  [ self fold: [:a :b| a, o, b ] ]
    ifFalse: [ (2 to: o) inject: self into: [:r :i| r, self ] ]!
/ n
  | r s |
  r := OrderedCollection new: (self size / n) ceiling.
  s := ReadStream on: self.
  [ r add: (s nextAvailable: n). s atEnd ] whileFalse.
  ^r!
\ b
  ^self collect: b!
\> b
  ^self \ [:x| (b value: x) displayNl ]!
<< o
  ^self add: o; yourself!
sum
  ^self fold: [:a :b| a + b]!
max
  ^self fold: [:a :b| a < b ifTrue: [ b ] ifFalse: [ a ] ]!
min
  ^self fold: [:a :b| a > b ifTrue: [ b ] ifFalse: [ a ] ]!

!BlockClosure methodsFor: 'golf'!
W
  ^self whileTrue!
U
  ^self whileFalse!
W: b
  ^self whileTrue:  b!
U: b
  ^self whileFalse: b!
* n
  ^n timesRepeat: self!

!FileStream methodsFor: 'golf'!
\ b
  ^(self contents subStrings: Character nl) \ b!
!
GolfDic := Dictionary new.
PseudoGlobal := {
  $< -> stdin.
  $> -> stdout.
  $* -> Smalltalk arguments.
  $S -> Smalltalk.
}D!

主な変更点:

  • ファイル名を小文字に,追加メソッド名を大文字に*1
  • GolfDic, PseudoGlobal
  • /でsplitもしくは分割*2,\でmap,\>でmap+puts*3
  • Boolean>>#i:i:が#ifFalse:ifTrueになってややこしいので#T:F:を定義
  • ^が使えないのでInteger>>#bitXor:は\
  • Collection>>#RでSqueakのatRandom(たぶん)
  • 「{key1->val1. key2->val2 ...}D」で辞書リテラルもどき
  • ** => ? (from GolfScript)
  • at: => @

実行例:

  • test.gst
(#Or withA:5y)\>[:x|x?2]@(2~4)P:$>y!
  • echo.gst
$<con P!
3R P!
  • Q.gst
0Q!
$ echo hoge | gst gost.st test.gst echo.gst 123.gst Q.gst
1
4
9
16
25
OrderedCollection (4 9 16 )
hoge

3
0Q!

*1:既存メソッドとの衝突を防ぐのと,数字の後に直接書けるようにするため

*2:'abcde'/2 => 'ab' 'cd' 'e'

*3:ブロックの各戻り値をP