Hatena::Grouprubyist

たばさの RSSフィード

12/19(水) 2007

めも

| めも - たばさの を含むブックマーク はてなブックマーク - めも - たばさの

http://golf.shinh.org/

http://www.darrenks.com/golfscript/index.html


スタックに積まれる。

入力はEOFまでスタックに積まれてからスクリプトが開始される。

 pipe使わなくてもいいけど、その場合はCtrl+Zしないと開始しないよ。

そして終了時にスタックにあるものすべてが出力される。


ということなので、echoはなにもしない。スタックだから逆順にしなきゃ駄目かとおもいきやそうではないようだ*1。そのた、簡単なものをとりあえず。

102:z;  # zを102と定義、;でスタックから取り除く。
z 1 -:z;  # z,1の順にスタックに積み、-でz-1を実行、それをzに入れ、;でスタックから取り除く。
{z 0 >}{z 1 -:z;z print " です。" puts}while; # z>0の間、ブロック(z=z-1、z表示)を繰り返す。

実行結果

(略)
8 です。
7 です。
6 です。
5 です。
4 です。
3 です。
2 です。
1 です。
0 です。

ちなみにz printの前の;を に変えると後ろにスタックに残った次のものが出力されるようですよ。

10099989796959493929190898887868584838281807978777675747372717069686766656463626
16059585756555453525150494847464544434241403938373635343332313029282726252423222
12019181716151413121110987654321

smileysをプリント。

| smileysをプリント。 - たばさの を含むブックマーク はてなブックマーク - smileysをプリント。 - たばさの

http://golf.shinh.org/p.rb?Smileys+Triangle

# smileys0.gs
':'puts
':-'puts
':-)':a;
0:i;
{i 32 <}{a . print; ['))'] i * '' * . print;i 1 +:i;n print;}while;

しかしスタックに積むだけでよい。

# smileys1.gs
':'n
':-'n
':-)':a;
0:i;
{i 32<}{a['))']i*''* i 1+:i;n}while

これも逆順じゃないんだな。なんかスタックっぽくないような。

電卓 続き 正規表現まわり

| 電卓 続き 正規表現まわり - たばさの を含むブックマーク はてなブックマーク - 電卓 続き 正規表現まわり - たばさの

履歴参照

# koneko-0.4.8.rb

$os="win"

require 'Win32API' if $os=="win"

$mode=""
$stack=[""]

$prompt=">"
$lprompt=">>"
$prprompt=":"
$repprompt="|>"
$show=false
$debug=false
$editor=""
$IOI="STDIN."

def keval(a,env)
  p a if $debug
  env.hlist.each{|v|
    a.gsub!(v,env.mem[env.assign[v]])
  }
  eval(a)
end

def reval a
  p a if $debug
  v=eval(a)
  p v
  v
end

def edit txt,editor=$editor
  if editor=="type"
    system("type #{txt}")
  elsif editor!=""
    `#{editor} #{txt}` 
  else
    browse txt
  end
end

def browse ur
  return if $os!="win"
  shellexecute = Win32API.new('shell32.dll','ShellExecuteA',%w(p p p p p i),'i')
  shellexecute.call(0, 'open', ur, 0, 0, 1)
end

class Env
 attr_accessor(:hlist,:assign,:mem,:his)
 def reset
   @mem=[]
   @hlist=[]
   @assign={}
   @his=[]
 end
end

$base = Env.new
$envs=["base"]
$base.reset
$current=$base
$currentname="base"
$hisfile="hensu-his.txt"

def showprompt
  print $currentname+$prompt
end

class Fv
 attr_accessor(:hlist,:assign,:name,:argv,:body)
end


def exist x,env
 env.hlist.member?(x)
end

def isarray? a,env
  / *(.*)/=~a
  a=$1
  env.hlist.each{|m|
    /#{calc(a,env)}\[/ =~ m
    # p m,$&
    return true if $&
  }
  false
end

def isstr? a,env
  exist a,env
end

def existusing x
 /(.*):(.*)/ =~ x
 return [false,nil,nil]if !$&
 $envs.each{|en|
   next if en!=$1
   env=eval("$"+en)
   return [true,env,$2] if exist($2,env)
   return [false,nil,nil]
 }
 [false,nil,nil]
end

def indmax ar,env
  i=0
  while exist(ar+"["+i.to_s+"]",env)
    i+=1
  end
  i
end

def existarray ar,env
  i=0
  exist(ar+"["+i.to_s+"]",env)
end

def arreset(ar,env)
  i=0
  while exist(ar+"["+i.to_s+"]",env)
    setvalstr(ar+"["+i.to_s+"]","",env)
    i+=1
  end
  i
end

def existf x,env
 /\(.*\)/ =~x
 return false if !$`
 name=$`
 env.hlist.each{|i|
  /\(.*\)/ =~i
  n=$`
 # p"exf",x,n,name,"$$"
  if $&
    if n==name
      return true
    end
  end
 }
 false
end

def getfunc x,env
 /\(([^\)]*)\)/ =~x
 vals=$1
 name=$`
 env.hlist.each{|i|
  /\(([^\)]*)\)/ =~i
  n=$`
  if $&
    if n==name
      arg =$1
      return [i,arg.split(','),vals.split(',')]
    end
  end
 }
 false
end

def set x,env
 n=0
 while 1
  (env.assign[x]=n ;env.mem[n]=""; break) if env.mem[n]==nil
  n+=1
 end
end

def argcalc arg,vals,a
  tmp=a.dup
  arg.length.times{|i|
    v=mainloop(vals[i])
    tmp.gsub!(arg[i],v)
  }
  mainloop(tmp)
end

# uhenchi
def calc d,env
 /^"([^"]*)"/ =~d
 str=$&
 mae=$`
 usr=$'
 if str
   tmp =$1.gsub("\\n","\n")
   /\#\{([^\}]*)\}/ =~ tmp
   if $&
     return calc(mae+"\""+$`+mainloop($1,env)+$'+"\""+usr,env)
   end
   return mae+tmp+usr if !$&
 end
 /^'([^']*)'/ =~d
 str=$&
 mae=$`
 usr=$'
 if str
   tmp =$1.gsub("\\n","\n")
   /\#\{([^\}]*)\}/ =~ tmp
   if $&
     return calc(mae+"\'"+$`+mainloop($1,env)+$'+"\'"+usr,env)
   end
   return mae+tmp+usr if !$&
 end
 /- *-[0-9]+/=~d
 d.gsub!(/- *-/,'+') if $&
 # func(..)
 /([a-zA-Z_][a-zA-Z_0-9]*\([^\)]+\))/ =~ d
 mae=$`
 usr=$'
 if $1
  if existf($1,env)
   f,arg,vals =getfunc($1,env)
   a = env.mem[env.assign[f]]
   a = argcalc(arg,vals,a)
   # p a,f,arg,vals,"$!$"
   return calc(mae+a.to_s+usr,env)
  else
   return calc(mae+usr,env)
  end
 end
 return calc($`+calc($1,env)+$',env) if $1
 # (...)
 /(.*)\(([^\)]+)\)(.*)/ =~ d
 return calc($1+calc($2,env)+$3,env) if $2
 # array
 /([a-zA-Z_0-9]+)\[([^\.])\.\.([^\.])\]/ =~d
 return calc($`+calc($1,env)[$2.to_i..$3.to_i]+$',env) if $&
 # ..*/..
 /([a-zA-Z_0-9\.\[\]]+ *[\*\/] *[a-zA-Z_0-9\.\[\]]+) *([+\/\*\-].+)/ =~ d
 return calc($`+calc($1,env)+$2,env) if $2
 # ..*/..
 /(.+[+\/\*\-]) *([a-zA-Z_0-9\.\[\]]+ *[\*\/] *[a-zA-Z_0-9\.\[\]]+)/ =~ d
 return calc($1+calc($2,env)+$',env) if $2
 # ..+-..
 /([a-zA-Z_0-9\.\[\]]+ *[+\-] *[a-zA-Z_0-9\.\[\]]+) *([+-].+)/ =~ d
 return calc($`+calc($1,env)+$2,env) if $2
 # p d
 /([a-zA-Z_0-9\.\[\]]+) *([+\*\-\/%]) *([a-zA-Z_0-9\.\[\]]+)/=~d
 a=$1
 si=$2
 c=$3
 if !a
  f,en,a = existusing(d)
  if f
   a =en.mem[en.assign[a]]
   return a.to_s
  elsif exist(d,env)
   a = env.mem[env.assign[d]]
   return a.to_s
  else 
   system(d[1..-1]) if d.class==String && d.length>0 && d[0,1]=="$"
   return d 
  end
 end
 if exist($1,env)
  a=env.mem[env.assign[$1]] 
 else
  a=$1
 end
 if exist($3,env)
  c=env.mem[env.assign[$3]] 
 else
  c=$3
 end
 /[^0-9e+\-\. ]/ =~ a.to_s
 f1=$&
 /[^0-9e+\-\. ]/ =~ c.to_s
 f2=$&
 return calc(a,env).to_s + calc(c,env).to_s if f2!=nil || f1!=nil
 return calc(eval(calc(a,env).to_s + si + calc(c,env).to_s ).to_s,env)
end

def getfname da
 / *(.+)/ =~ da
 file =$1
 if !$1
   file ="mylog.txt" 
 else
   /\./ =~file
   file =file+".ko" if !$&
 end
 file
end

def getstr da
 / *(.+)/ =~ da
 file =$1
 file ="" if !$1
 file
end

def memo env
 open($hisfile,'a'){|f|
  f.puts env.his
 }
end

def funccalc a,b,c
  fn=Fv.new
  fn.name=a
  fn.argv=b.split(',')
  fn.body=c
  fn
end

def setval a,b,env,eva=false
  (env.hlist<<a) if !exist a,env
  set a,env if env.assign[a]==nil 
  envfrom=env
  f,en,v =existusing(b)
  (envfrom=en;b=v) if f
  if eva
    v=b
  else
    v=calc(b,envfrom)
    v="nul" if v==nil
  end
  env.mem[env.assign[a]] =v
  return env.mem[env.assign[a]]
end

def setvalstr a,b,env
  setval a,b,env,true
end

def geteditor env
  return "" if !env.hlist.member?("editor")
  env.mem[env.assign["editor"]]
end

def mainloop da,env=$base
 env.his<<da
 p "m:"+da if $debug
 # comment
 # p
 / *p  *(.*)/ =~ da
 if $&
   p mainloop($1,env)
   return $` 
 end
 # regexp
 /\/[^\/]+\/ *=~.*/ =~ da
 eval($&) if $&
 eval("$match=$~") if $&
 if $1
   9.times{|i|
     p eval("$#{i+1}") if $debug
     eval("setval(\"$#{i+1}\",$#{i+1},env)") 
   }
   setval("$&",$&,env)
   setval("$`",$`,env)
   setval("$'",$',env)
 end
 # file :write array
 /file\(([^\)]+)\) *(=|<<) *(.*)/ =~ da
 f=$1
 op=$2
 a=$3
 if f
   /(.*),(.*)/ =~ f
   if $&
     f=$1
     mode=$2
   else
     mode='w' if op=='='
     mode='a' if op=='<<'
   end
   open(f,mode){|fo|
     if existarray(a,env)
       imax=ii=indmax(a,env)
       while ii>0
         line=calc(a+"["+(imax-ii).to_s+"]",env)
         fo.puts(line)
         ii-=1
       end
     elsif !exist(a,env)
       fo.puts(calc(a,env))
     else
       fo.puts(a)
     end
   }
   return ""
 end
 # function
 /([a-zA-Z_][a-zA-Z_0-9]*\((.*)\)) *=(.+)/ =~ da
 if $&
   a=funccalc $1,$2,$3
   # p a
   env.hlist<<a.name if !exist a.name,env
   set a.name,env if env.assign[a.name]==nil 
   env.mem[env.assign[a.name]]=$3 #calc($3,env)
   return a.name
 end
 # while
 /while  *([^><=]+)(!?[=><]+)(.+)  *\{([^\}]+)\}/ =~ da
 mae,usr,m1,m2,m3,body =$`,$',$1,$2,$3,$4
 if $1
  ans =calc($1,env)+$2+calc($3,env)
  if eval(ans)
    / *break */=~ mainloop(body,env)
    if $&
      return mainloop(mae+usr,env)
    end
    return mainloop(mae+"while "+m1+m2+m3+" {"+body+"}"+usr,env)
  else
    return mainloop(mae+usr,env)
  end
 end
 /while  *([^\{]+)  *\{([^\}]+)\}/ =~ da
 mae,usr,cond,body =$`,$',$1,$2
 if cond
  ans =mainloop(cond,env)
  if ans
    / *break */=~ mainloop(body,env)
    if $&
      return mainloop(mae+usr,env)
    end
    return mainloop(mae+"while "+cond+" {"+body+"}"+usr,env)
  else
    return mainloop(mae+usr,env)
  end
 end
 # num.times
 /([a-zA-Z_0-9]+)\.times *\{ *([^\}]+) *\}/ =~ da
 body=$2
 if $&
  num=calc($1,env).to_i
  return num.times{ |it|
    a=body.gsub("it", it.to_s)
    a=a.gsub("ti", (num-it).to_s)
    print "(#{a})",$repprompt if $debug
    / *break */=~ mainloop(a,env)
    break if $&
  }
 end
 # gets
 /gets(\([^\)]*\))?/ =~ da
 if $&
   inp=$IOI+$&
   a=eval(inp)
   setval("$_",$_,env)
   return a if $`=="" && $'==""
   a="" if a==nil
   return mainloop($`+a+$',env)
 end
 # multi
 /([^;]*);(.*)/ =~ da
 m1=$1
 m2=$2
 if $1
   ans =mainloop $1,env
   / *break */ =~ ans
   return "break" if $&
   return mainloop(m2,env)
 end
 /if  *(.+)([!=]=)(.+)  *then *(.+)/ =~ da
 mae,usr,m1,m2,m3,mtrue =$`,$',$1,$2,$3,$4
 if $1
  p $& if $debug
  /else  *(.*)/ =~ mtrue
  mfalse =$1
  mtrue =$` if $&
  p $& if $debug
  if m2=="=="
   if calc(m1,env)==calc(m3,env)
    return mainloop(mae +mtrue +usr,env) 
   else
    if mfalse
      return mainloop(mae+mfalse+usr,env)
    else
      return mainloop(mae+usr,env)
    end
   end
  else
   if calc(m1,env)!=calc(m3,env)
    return mainloop(mae+mtrue+usr,env)
   else
    if mfalse
      return mainloop(mae+mfalse+usr,env)
    else
      return mainloop(mae+usr,env)
    end
   end
  end
 end
 /if  *(.+)<(.+)  *then (.+)  *else  *(.+)/ =~ da
 if $1
  if calc($1,env)<calc($2,env)
    return mainloop($`+$3+$',env)
  else
    return mainloop($`+$4+$',env)
  end
 end
 /if  *(.+)>(.+)  *then (.+)  *else  *(.+)/ =~ da
 if $1
  if calc($1,env)>calc($2,env)
    return mainloop($`+$3+$',env)
  else
    return mainloop($`+$4+$',env)
  end
 end
 # print
 /print  *((.|\n)+)/ =~ da
 strs=$1
 if strs
   /(.*),(.*)/ =~ strs
   m1=$1
   m2=$2
   #/"/ =~ strs
   if m1 # !$& && m1
     return (mainloop("print #{m1}");mainloop("print #{m2}"))
   else
     a= calc(strs,env)
     print a
     return (mainloop($`.to_s+a+$'.to_s) )
   end
 end
 # puts
 /puts  *((.|\n)+)/ =~ da
 strs=$1
 if strs
   /(.*),(.*)/ =~ strs
   m1=$1
   m2=$2
   #/"/ =~ strs
   if m1
     return (mainloop("puts #{m1}");mainloop("puts #{m2}")) 
   else
     a= calc(strs,env)
     puts a
     return (mainloop($`.to_s+a+$'.to_s) )
   end
 end
 # browse
 /^http.*/ =~ da
 browse($&) if $&
 # browse
 /.*\.txt/ =~ da
 editor=""
 editor=geteditor(env) if exist("editor",env)
 edit($&,editor) if $&
 # reval
 /(([a-zA-Z_][a-zA-Z_0-9]*)(\[ *([0-9]+) *\])?) *= *([rk]eval.+)/ =~ da
 a=$1
 a=$2+"["+$3+"]" if $3
 rk=$5
 if a
   /keval\( *([^,]*)(, *.+)?\)/ =~rk
   rk="keval("+$1+",env)" if !$2 && $1
   return setval(a, eval(rk).to_s,env,true)
 end
 # file to Array
 /(([a-zA-Z_][a-zA-Z_0-9]*)(\[ *([0-9]+) *\])?) *(=|<<) *file\( *(.+) *\)/ =~ da
 a=$2
 ind=$4
 op=$5
 f=$6
 if a
   mode="r"
   /(.*) *, *(.*)/ =~ f
   if $&
     f=$1
     mode=$2
   end
   tmp=[]
   /^"(.*)"$/ =~ f
   f=$1 if $&
   open(f,mode){|fi|
     tmp=fi.readlines
   }
   #p tmp
   start=indmax(a,env)
   (arreset(a,env) ; start=0) if op=='=' && !ind
   start=ind.to_i if ind
   tmp.length.times{|i|
     puts a+"[#{i+start}]",tmp[i] if $debug
     setval(a+"[#{i+start}]",tmp[i],env,true)
   }
   return ""
 end
 # simple equation
 /([a-zA-Z_][a-zA-Z_0-9]*(\[[0-9]+\])?) *= *(.+)/ =~ da
 a=$1
 b=$3
 if a
   return setval(a,b,env)
 else
   if da=="??"
     env.hlist.each{|i| 
       puts $prprompt+i+"= '"+env.mem[env.assign[i]].to_s+"'"
     }
     return""
   elsif da=="?"
     puts env.hlist*","
     return ""
   elsif da=="???" || da=="?3"
     p env.mem,env.hlist,env.assign
     return ""
   elsif da=="his"
     p env.his
     return ""
   elsif da=="hiss"
     return memo(env)
   elsif da=="hisl"
     return mainloop("!load #{$hisfile}",env)
   elsif exist(da,env) 
     a=env.mem[env.assign[da]]
     system(a[1..-1]) if a.class==String && a[0..0]=="$"
     return a
   elsif da=="????" || da=="?4"
     print "hensuu:\t"
     p env.hlist
     print "assign:\t"
     p env.assign
     print "memory:\t"
     p env.mem
     print "env:\t"
     p $envs
     puts
     return ""
   elsif da=="?????" || da=="?5"
     $envs.each{|e|
       puts "env::"+":"*30+"("+e+")"
       mainloop("?",eval("$"+e))
     }
     puts
     return ""
   elsif da=="??????" || da=="?6"
     $envs.each{|e|
       puts "env:"+"."*30+" ("+e+")"
       mainloop("????",eval("$"+e))
     }
     return ""
   elsif da=="???????" || da=="?e"
     $envs.each{|e|
       p eval("$"+e)
     }
     return ""
   elsif da=='$'
     exit
   elsif da=='exit'
     memo env
     exit
   elsif da[0..9]=='@namespace' || da[0..2]=='@ns' 
     /[^ ]+ *(.*)/ =~ da
     if !$1
       p env
       return ""
     end
     envname=getstr $1
     (p $envs;return"") if envname==""
     if ! $envs.member?(envname)
       name="$#{envname}"
       eval(name+"=Env.new")
       $envs<<envname
       eval("$current="+name)
       $current.reset
     else
       eval("$current=$"+envname)
     end
     $currentname=envname
     mainloop("?",$current)
     return""
   elsif da=='help'
     help
     return ""
   elsif da=='show'
     $show=!$show
     return ""
   elsif da=='debug'
     $show=true
     $debug=true
     return ""
   elsif da=='undebug'
     $show=false
     $debug=false
     return ""
   elsif da[0,8]=="isarray?"
     a=isarray?(da[8..-1],env).to_s
     puts a
     return a
   elsif da=='reset'
     env.reset
     return ""
   elsif da[0,4]=='keval'
     p keval(da[5..-1],env)
     return ""
   elsif da[0,5]=='reval'
     a = reval(da[6..-1])
     p a
     return a
   elsif da[0,6]=='$eopen'
     file =getfname da[6..-1]
     edit(file,geteditor(env))
     return ""
   elsif da[0,1]=='$'
     puts da[1..-1]
     system(da[1..-1])
     return ""
   elsif da[0,5]=="!load"
     loadf da[5..-1]
     return ""
     # puts "loaded \'#{file}\'."
   elsif da[0,2]=="!l"
     loadf da[2..-1]
     return ""
   elsif da[0,5]=="!save"
     file =getfname da[5..-1]
     open(file,"a"){|f| 
       env.hlist.each{|i| 
         f.puts i.to_s+"="+env.mem[env.assign[i]].to_s
       }
     }
     return "saved as \'#{file}\'."
   else
     a=calc(da,env)
     return a
   end
 end
end

def help
 puts "example: 'x=1','y=text','?'(list),'z=x*2+(5-x)','!save [file]'(file save),'!load [file]', '???'(internal hensu dump),'$dir'(exec system.command) etc."
end

# check whether this block is a single line
def blockok d
  flag = false
  a=d.gsub(/[^\{\}]/,'')
  a=a.gsub(/\{\}/,'')
  while $& ;a=a.gsub(/\{\}/,'') end
  #p "a=",a
  return false if a!="" 
  /puts *"((.|\n)*)/ =~ d
  if $&
    #p "qst:"+$1+".m:"+$&
    /"/ =~$1
    if !$&
      return false
    end
  end
  /print *"[^"]*$/ =~ d
  return false if $&
  true
end

def commentoff da
  /[ \t]*#.*/ =~da
  flag =false
  a =$&
  b =$`
  if a
    flag =true
    /^\{[^\}]+\}/ =~a
    flag =false if $&
    /\"/ =~a
    flag =false if $&
  end
  return b if flag
  da
end


def main da, env=$current
  line=$stack.pop 
  data=commentoff(da.chomp)
  ($stack.push(""); return "") if data=="" && line==""
  if line!=""
    /^[^\\]*\"[^\"]*$/ =~ line 
    if $&
      line = line +"\n" + da.chomp
    else
      line = line+";"+ data
    end
  else
    line = data
  end
  p "l:"+line if $debug
  $stack.push(line) 
  if blockok(line)
    p"blk:"+line if $debug
    an=mainloop(line,env)
    puts an if $show
    mainloop("??",env) if $debug
    showprompt if $mode!="load" || $show
    $stack.pop
    line=""
    $stack.push(line)
  else
    print $repprompt if $mode!="load" || $show
  end
end


def loadf fname
 $mode="load"
 file =getfname fname
 open(file,"r"){|f|
   n=0
   $stack.push("")
   f.each{|dat|
     n+=1
     #p dat
     puts n.to_s+":"+dat+"("+fname +")" if $show
     main(dat)
   }
   $stack.pop
 }
 $mode=""
end


### start ###

if ARGV==[]
  # dialog mode
  showprompt
  while gets
    main $_, $current
  end
else
  # file load mode
  loadf ARGV[0]
end

*1:文字列がEOFまで1データとして積まれる

トラックバック - http://rubyist.g.hatena.ne.jp/hatecha/20071219
カレンダー
<< 2007/12 >>
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
archive Error : RSSが取得できませんでした。