fork download
  1. #!/usr/local/bin/ruby
  2. #(c) Copyright 2008 Darren Smith. All Rights Reserved.
  3. $lb = []
  4. class Gtype
  5. def go
  6. $stack<<self
  7. end
  8. def val
  9. @val
  10. end
  11.  
  12. '+-|&^'.each_byte{|i|
  13. eval'def %c(rhs)
  14. if rhs.class != self.class
  15. a,b=coerce(rhs)
  16. a %c b
  17. else
  18. factory(@val %c rhs.val)
  19. end
  20. end'%([i]*3)
  21. }
  22. def ==(rhs)
  23. @val==rhs.val
  24. end
  25. def eql?(rhs)
  26. @val==rhs.val
  27. end
  28. def hash
  29. @val.hash
  30. end
  31. def <=>(rhs)
  32. @val<=>rhs.val
  33. end
  34. end
  35.  
  36. class Gint < Gtype
  37. def initialize(i)
  38. @val = case i
  39. when true then 1
  40. when false then 0
  41. else;i
  42. end
  43. end
  44. def factory(a)
  45. Gint.new(a)
  46. end
  47. def to_gs
  48. Gstring.new(@val.to_s)
  49. end
  50. def to_int #for pack
  51. @val
  52. end
  53. def ginspect
  54. to_gs
  55. end
  56. def class_id; 0; end
  57. def coerce(b)
  58. [if b.class == Garray
  59. Garray.new([self])
  60. elsif b.class == Gstring
  61. to_gs
  62. else #Gblock
  63. to_gs.to_s.compile
  64. end,b]
  65. end
  66.  
  67. def ~
  68. Gint.new(~@val)
  69. end
  70. def notop
  71. Gint.new(@val == 0)
  72. end
  73. '*/%<>'.each_byte{|i|
  74. eval'def %c(rhs)
  75. Gint.new(@val %c rhs.val)
  76. end'%[i,i]
  77. }
  78. def equalop(rhs)
  79. Gint.new(@val == rhs.val)
  80. end
  81. def question(b)
  82. Gint.new(@val**b.val)
  83. end
  84. def base(a)
  85. if Garray===a
  86. r=0
  87. a.val.each{|i|
  88. r*=@val
  89. r+=i.val
  90. }
  91. Gint.new(r)
  92. else
  93. i=a.val.abs
  94. r=[]
  95. while i!=0
  96. r.unshift Gint.new(i%@val)
  97. i/=@val
  98. end
  99. Garray.new(r)
  100. end
  101. end
  102. def leftparen
  103. Gint.new(@val-1)
  104. end
  105. def rightparen
  106. Gint.new(@val+1)
  107. end
  108. end
  109.  
  110. class Garray < Gtype
  111. def initialize(a)
  112. @val = a
  113. end
  114. def factory(a)
  115. Garray.new(a)
  116. end
  117. def to_gs
  118. @val.inject(Gstring.new("")){|s,i|s+i.to_gs}
  119. end
  120. def flatten #maybe name to_a ?
  121. Garray.new(@val.inject([]){|s,i|s+case i
  122. when Gstring then i.val
  123. when Gint then [i]
  124. when Garray then i.flatten.val
  125. when Gblock then i.val
  126. end
  127. })
  128. end
  129. def ginspect
  130. Gstring.new('[')+Garray.new(@val.map{|i|i.ginspect})*Gstring.new(' ')+Gstring.new(']')
  131. end
  132. def go
  133. $stack<<self
  134. end
  135. def class_id; 1; end
  136. def coerce(b)
  137. if b.class == Gint
  138. b.coerce(self).reverse
  139. elsif b.class == Gstring
  140. [Gstring.new(self),b]
  141. else
  142. [(self*Gstring.new(' ')).to_s.compile,b]
  143. end
  144. end
  145.  
  146. def leftparen
  147. [factory(@val[1..-1]),@val[0]]
  148. end
  149. def rightparen
  150. [factory(@val[0..-2]),@val[-1]]
  151. end
  152. def *(b)
  153. if b.class == Gint
  154. factory(@val*b.val)
  155. else
  156. return b*self if self.class == Gstring && b.class == Garray
  157. return self/Gint.new(1)*b if self.class == Gstring
  158. return b.factory([]) if @val.size<1
  159. r=@val.first
  160. r,x=r.coerce(b) if r.class != b.class #for size 1
  161. @val[1..-1].each{|i|r=r+b+i}
  162. r
  163. end
  164. end
  165. def /(b)
  166. if b.class == Gint
  167. r=[]
  168. a = b.val < 0 ? @val.reverse : @val
  169. i = -b = b.val.abs
  170. r << factory(a[i,b]) while (i+=b)<a.size
  171. Garray.new(r)
  172. else
  173. r=[]
  174. i=b.factory([])
  175. j=0
  176. while j<@val.size
  177. if @val[j,b.val.size]==b.val
  178. r<<i
  179. i=b.factory([])
  180. j+=b.val.size
  181. else
  182. i.val<<@val[j]
  183. j+=1
  184. end
  185. end
  186. r<<i
  187. Garray.new(r)
  188. end
  189. end
  190. def %(b)
  191. if b.class == Gint
  192. b=b.val
  193. factory((0..(@val.size-1)/b.abs).inject([]){|s,i|
  194. s<<@val[b < 0 ? i*b - 1 : i*b]
  195. })
  196. else
  197. self/b-Garray.new([Garray.new([])])
  198. end
  199. end
  200. def notop
  201. Gint.new(@val.empty?)
  202. end
  203. def question(b)
  204. Gint.new(@val.index(b)||-1)
  205. end
  206. def equalop(b)
  207. if b.class == Gint
  208. @val[b.val]
  209. else
  210. Gint.new(@val==b.val)
  211. end
  212. end
  213. def <(b)
  214. if b.class == Gint
  215. factory(@val[0...b.val])
  216. else
  217. Gint.new(@val<b.val)
  218. end
  219. end
  220. def >(b)
  221. if b.class == Gint
  222. factory(@val[[b.val,-@val.size].max..-1])
  223. else
  224. Gint.new(@val>b.val)
  225. end
  226. end
  227. def sort
  228. factory(@val.sort)
  229. end
  230. def zip
  231. r=[]
  232. @val.size.times{|x|
  233. @val[x].val.size.times{|y|
  234. (r[y]||=@val[0].factory([])).val<<@val[x].val[y]
  235. }
  236. }
  237. Garray.new(r)
  238. end
  239. def ~
  240. val
  241. end
  242. end
  243.  
  244. class Gstring < Garray
  245. def initialize(a)
  246. @val=case a
  247. when String then a.unpack('C*').map{|i|Gint.new(i)}
  248. when Array then a
  249. when Garray then a.flatten.val
  250. end
  251. end
  252. def factory(a)
  253. Gstring.new(a)
  254. end
  255. def to_gs
  256. self
  257. end
  258. def ginspect
  259. factory(to_s.inspect)
  260. end
  261. def to_s
  262. @val.pack('C*')
  263. end
  264. def class_id; 2; end
  265. def coerce(b)
  266. if b.class == Gblock
  267. [to_s.compile,b]
  268. else
  269. b.coerce(self).reverse
  270. end
  271. end
  272. def question(b)
  273. if b.class == Gstring
  274. Gint.new(to_s.index(b.to_s)||-1)
  275. elsif b.class == Garray
  276. b.question(self)
  277. else
  278. Gint.new(@val.index(b)||-1)
  279. end
  280. end
  281. def ~
  282. to_s.compile.go
  283. nil
  284. end
  285. end
  286.  
  287. class Gblock < Garray
  288. def initialize(a,b=nil)
  289. @val=Gstring.new(b).val
  290. @native = eval("lambda{#{a}}")
  291. end
  292. def go
  293. @native.call
  294. end
  295. def factory(b)
  296. Gstring.new(b).to_s.compile
  297. end
  298. def class_id; 3; end
  299. def to_gs
  300. Gstring.new("{"+Gstring.new(@val).to_s+"}")
  301. end
  302. def ginspect
  303. to_gs
  304. end
  305. def coerce(b)
  306. b.coerce(self).reverse
  307. end
  308.  
  309. def +(b)
  310. if b.class != self.class
  311. a,b=coerce(b)
  312. a+b
  313. else
  314. Gstring.new(@val+Gstring.new(" ").val+b.val).to_s.compile
  315. end
  316. end
  317. def *(b)
  318. if b.class == Gint
  319. b.val.times{go}
  320. else
  321. gpush b.val.first
  322. (b.val[1..-1]||[]).each{|i|$stack<<i; go}
  323. end
  324. nil
  325. end
  326. def /(b)
  327. if b.class==Garray||b.class==Gstring
  328. b.val.each{|i|gpush i; go}
  329. nil
  330. else #unfold
  331. r=[]
  332. loop{
  333. $stack<<$stack.last
  334. go
  335. break if gpop.notop.val!=0;
  336. r<<$stack.last
  337. b.go
  338. }
  339. gpop
  340. Garray.new(r)
  341. end
  342. end
  343. def %(b)
  344. r=[]
  345. b.val.each{|i|
  346. lb=$stack.size
  347. $stack<<i; go
  348. r.concat($stack.slice!(lb..$stack.size))
  349. }
  350. r=Garray.new(r)
  351. b.class == Gstring ? Gstring.new(r) : r
  352. end
  353. def ~
  354. go
  355. nil
  356. end
  357. def sort
  358. a=gpop
  359. a.factory(a.val.sort_by{|i|gpush i; go; gpop})
  360. end
  361. def select(a)
  362. a.factory(a.val.select{|i|gpush i;go; gpop.notop.val==0})
  363. end
  364. def question(b)
  365. b.val.find{|i|gpush i; go; gpop.notop.val==0}
  366. end
  367. end
  368.  
  369. class NilClass
  370. def go
  371. end
  372. end
  373. class Array
  374. def ^(rhs)
  375. self-rhs|rhs-self
  376. end
  377. include Comparable
  378. end
  379. code=gets(nil)||''
  380. $_=$stdin.isatty ? '' : $stdin.read
  381. $stack = [Gstring.new($_)]
  382. $var_lookup={}
  383.  
  384. def var(name,val=nil)
  385. eval"#{s="$_#{$var_lookup[name]||=$var_lookup.size}"}||=val"
  386. s
  387. end
  388.  
  389. $nprocs=0
  390.  
  391. class String
  392. def compile(tokens=scan(/[a-zA-Z_][a-zA-Z0-9_]*|'(?:\\.|[^'])*'?|"(?:\\.|[^"])*"?|-?[0-9]+|#[^\n\r]*|./m))
  393. orig=tokens.dup
  394. native=""
  395. while t=tokens.slice!(0)
  396. native<<case t
  397. when "{" then "$stack<<"+var("{#{$nprocs+=1}",compile(tokens))
  398. when "}" then break
  399. when ":" then var(tokens.slice!(0))+"=$stack.last"
  400. when /^["']/ then var(t,Gstring.new(eval(t)))+".go"
  401. when /^-?[0-9]+/ then var(t,Gint.new(t.to_i))+".go"
  402. else; var(t)+".go"
  403. end+"\n"
  404. end
  405. source=orig[0,orig.size-tokens.size-(t=="}"?1:0)]*""
  406. Gblock.new(native,source)
  407. end
  408. end
  409. def gpop
  410. ($lb.size-1).downto(0){|i|
  411. break if $lb[i]<$stack.size
  412. $lb[i]-=1
  413. }
  414. $stack.pop
  415. end
  416. def gpush a
  417. $stack.push(*a) if a
  418. end
  419.  
  420. class String
  421. def cc
  422. Gblock.new(self)
  423. end
  424. def cc1
  425. ('a=gpop;'+self).cc
  426. end
  427. def cc2
  428. ('b=gpop;a=gpop;'+self).cc
  429. end
  430. def cc3
  431. ('c=gpop;b=gpop;a=gpop;'+self).cc
  432. end
  433. def order
  434. ('b=gpop;a=gpop;a,b=b,a if a.class_id<b.class_id;'+self).cc
  435. end
  436. end
  437.  
  438. var'[','$lb<<$stack.size'.cc
  439. var']','gpush Garray.new($stack.slice!(($lb.pop||0)..-1))'.cc
  440. var'~','gpush ~a'.cc1
  441. var'`','gpush a.ginspect'.cc1
  442. var';',''.cc1
  443. var'.','$stack<<a<<a'.cc1
  444. var'\\','$stack<<b<<a'.cc2
  445. var'@','$stack<<b<<c<<a'.cc3
  446. var'+','gpush a+b'.cc2
  447. var'-','gpush a-b'.cc2
  448. var'|','gpush a|b'.cc2
  449. var'&','gpush a&b'.cc2
  450. var'^','gpush a^b'.cc2
  451. var'*','gpush a*b'.order
  452. var'/','gpush a/b'.order
  453. var'%','gpush a%b'.order
  454. var'=','gpush a.equalop(b)'.order
  455. var'<','gpush a<b'.order
  456. var'>','gpush a>b'.order
  457. var'!','gpush a.notop'.cc1
  458. var'?','gpush a.question(b)'.order
  459. var'$','gpush (a.class==Gint ? $stack[~a.val] : a.sort)'.cc1
  460. var',','gpush case a
  461. when Gint then Garray.new([*0...a.val].map{|i|Gint.new(i)})
  462. when Gblock then a.select(gpop)
  463. when Garray then Gint.new(a.val.size)
  464. end'.cc1
  465. var')','gpush a.rightparen'.cc1
  466. var'(','gpush a.leftparen'.cc1
  467.  
  468. var'rand','gpush Gint.new(rand([1,a.val].max))'.cc1
  469. var'abs','gpush Gint.new(a.val.abs)'.cc1
  470. var'print','print a.to_gs'.cc1
  471. var'if',"#{var'!'}.go;(gpop.val==0?a:b).go".cc2
  472. var'do',"loop{a.go; #{var'!'}.go; break if gpop.val!=0}".cc1
  473. var'while',"loop{a.go; #{var'!'}.go; break if gpop.val!=0; b.go}".cc2
  474. var'until',"loop{a.go; #{var'!'}.go; break if gpop.val==0; b.go}".cc2
  475. var'zip','gpush a.zip'.cc1
  476. var'base','gpush b.base(a)'.cc2
  477.  
  478. '"\n":n;
  479. {print n print}:puts;
  480. {`puts}:p;
  481. {1$if}:and;
  482. {1$\if}:or;
  483. {\!!{!}*}:xor;
  484. '.compile.go
  485. code.compile.go
  486. gpush Garray.new($stack)
  487. 'puts'.compile.go
Success #stdin #stdout 0.01s 5028KB
stdin
'4' '3' ~\1{1{*}?}{@\+@*}:?~
stdout
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096