Skip to content

Instantly share code, notes, and snippets.

@pumbur
Last active December 22, 2018 09:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pumbur/2df08af2ad846ace75fa to your computer and use it in GitHub Desktop.
Save pumbur/2df08af2ad846ace75fa to your computer and use it in GitHub Desktop.
class Object
def main?; (TOPLEVEL_BINDING.eval('self')==self) rescue (self.inspect=='main') end
def main_eval(&b); (main? ? Kernel : self).module_eval(&b); end
def aka(q); main_eval{ q.each{|k,v| alias_method(k,v) }}; end
def act(*q); main_eval{ q.each_slice(2){|a,b| define_method(a,&b) }}; end
def slf(*q); main_eval{ q.each_slice(2){|a,b| define_singleton_method(a,&b) }}; end
def to_sym; to_s.to_sym; end
def self; self; end
end
class Regexp; end
class Rational; end
Kernel.slf :class_alias, ->(n,c){
Kernel.const_set(n.capitalize,c)
Kernel.act(n.capitalize,->(*a,&b){ c.act?(:new) ? c.new(*a,&b) : Kernel.send(c.to_sym,*a,&b) })
Kernel.act(:"#{n}?",->{is_a? c})
}
{obj:Object,num:Numeric,enu:Enumerable,enm:Enumerator,rng:Range,ary:Array,hsh:Hash,
sym:Symbol,str:String,prc:Proc,rgx:Regexp,rat:Rational,int:Integer}.each{|n,c| Kernel.class_alias(n,c) }
Obj.act :lap, ->(&b){ b ? b[self] : self },
:lif, ->(s=nil,&b){ (s==true)||(s!=false)&&self.lap(&s) ? b[self] : self },
:laps,->(*b){ b.inject(self){|s,b| s.lap(&b) }},
:cloned,->{ Marshal.load(Marshal.dump(self)) },
:ne?, ->{ self && (!empty?) && self },
:act?,->(q){ respond_to?(q,true) },
:bit?,->{ is_a?(TrueClass) || is_a?(FalseClass) },
:int?,->{ num? && (self%1).zero? }
Num.act :pos?,->{ self>0 }, :neg?,->{ self<0 }, :inc,->q=1{ self+q }, :dec,->q=1{ self-q }, :inv,->{ -self },
:neg,->{ pos? ? inv : self }, :pos,->{ neg? ? inv : self }, :ext,->q=1{ self+sgn*q },
:par, ->{ zero? ? 0 : odd? ? 1 : -1 }, :sgn, ->{ pos? ? 1 : neg? ? -1 : 0 },
:to_enum,->{ neg? ? (self..-1) : (0...self) }, :to_b,->{ self!=0 }, :to_a,->{ to_enum.to_a },
:zero?, ->{ self==0 }, :nz?, ->{ (self==0) ? nil : self }
Num.act :fold,->(*q,&b){ to_enum.inject(*q,&b) },
:each,->(&b){ to_enum.each(&b) }, :map, ->(&b){ to_enum.map(&b) }, :fmap,->(&b){ to_enum.fmap(&b) },
:sum, ->(i=0,&b){ (self.to_enum+i).sum(&b) },
:prod, ->(i=1,&b){ (self.to_enum+i).prod(&b) },
:divmods, ->(*q){ q.fold([self]){|o,q| o[0],t=o[0].divmod(q); o<< t }},
:clamp, ->(n,x=nil){ n,x=n.minmax if n.rng?; n||=self; x||=self; (self<n) ? n : (self>x) ? x : self }
Int.act :digits, ->(d=10,s=nil){ return nil if d<2; n,o,s=self,[],s&&(s+1)||s; (n,a=n.divmod(d); o << a) while (s&&(s-=1)||n)>0; o },
:slices,->(*a,&b){ digits(2).slices(*a).map{|q| q.flip.join('').to_i(2) } },
:[], ->(a,b=1){ a,b=a.begin,a.size if a.rng?; (self >> a) & ((1 << b) - 1) }
Enu.act :qap, ->(a,*b,&c){ a.prc? ? map{|q| a[q,*b] } : map{|q| q.send(a,*b,&c) } },
:mapa, ->(&b){ map{|q| b[*q] } },
:mapi, ->(&b){ each_with_index.map(&b) },
:mapr, ->(w=0,&b){ (q=w.neg? ? b[self,w.abs] : self).ary? ? q.map{|q| q.enu? ? q.mapr(w.ext,&b) : b[q,w.abs] }.lap{|q| w.pos? ? b[q,w] : q } : b[q,w] },
:mapf, ->(i=0,&b){ map{|q| ((q.enu?&&(i!=0)) ? q.mapf(i-1,&b) : b[q]) }},
:sum, ->(i=0,&b){ map(&b).fold(i,&:+) },
:prod, ->(i=1,&b){ map(&b).fold(i,&:*) },
:sift, ->(q=nil,&b){ q&&q.act?(:===) ? grep(q) : select(&b) },
:lose, ->(q=nil,&b){ q&&q.act?(:===) ? grep_v(q) : reject(&b) },
:slices,->(*a,&b){ s,o=self,[]; (o << (b||->q{q})[s[0,a[0]||=size]]; s = s[a[0]..-1]||[]; a = a.rest if a.size>1) while s.ne?; o },
:cons, ->(n=2,&b){ each_cons(n).map(&b) },
:sort?, ->(&b){ (self==sort(&b)) },
:uniq?, ->(&b){ (self==uniq(&b)) },
:count_by, ->(&b){ fold({}){|o,q| o[q=(b ? b[q] : q)]||=0; o[q]+=1; o }},
:indexes, ->(a=nil,&b){ b = a.method(:===) if a; each_with_index.fold([]){|o,(q,i)| o << i if b[q]; o } },
:fmap, ->(&b){ fold([]){|o,q| (q=q.lap(&b)).enu? ? (o+q.to_a) : (o<< q) } }
Enu.aka fold: :inject, eachi: :each_with_index
Ary.act :rest, ->(i=1){ i.neg? ? self[0...i] : (size<i) ? [] : self[i..-1] },
:products, ->{ empty? ? [] : head.product(*rest) },
:same?, ->(&b){ map(&b).cons(2).all?{|a,b| a==b } },
:ids, ->(*q,&b){ b.prc? ? each_index.select{|i| b[self[i]] } : q.map{|q| index(q) } },
:swap, ->(q){ q.zip(self.vals(*q).move(-1)).fold(self){|o,(a,b)| o[a]=b; o } },
:coat, ->(*q){ q.fmap(&:mapi).fold(self){|o,(q,i)| o[i]=q if !q.nil?; o }},
:slice_at, ->(*q){ q<< size; i=0; q.map{|q| self.shift(-i+(i=q)) } },
:split,->(q=nil,&b){ [-1,*ids{|w| b.prc? ? b[w] : q.act?(:===) ? (q===w) : (q==w) },size].cons(2){|a,b| self[a.inc...b] } },
:depth,->{ (sift(&:ary?).map(&:depth).max||0).inc },
:to_i, ->(d){ (d.ary?||(d.int?&&(d=d.to_a)))&&flip.eachi.fold(0){|o,(q,i)| o+(d.id(q)*(d.size**i)) }||0 },
:prefix_size, ->(i=0,m=map(&:size).max){ i+=1 while (i<m) && map{|q| q[i] }.same?; i },
:turn_safe, ->n=0{ empty? ? [[]]*n : (map(&:size).max||0).map{|i| map{|q| q[i] } } },
:and, ->b{ ((a=self.count_by).keys|(b=b.count_by).keys).fmap{|q| [q]*[a[q]||0,b[q]||0].min } },
:sub, ->b{ b=b.count_by; self.count_by.fmap{|k,v| [k]*[v-(b[k]||0),0].max } }
Ary.act :rfind, ->*a,&b{ reverse.find(*a,&b) }, :rsort, ->(&b){ sort(&b).reverse }, :rsort_by, ->(&b){ sort_by(&b).reverse }
Ary.aka len: :length, head: :first, vals: :values_at, flip: :reverse, flat: :flatten, inc?: :include?, id: :index, move: :rotate
Hsh.act :sift, ->(&b){ Hash[select(&b)] },
:lose, ->(&b){ Hash[reject(&b)] }
Hsh.act :mapk, ->(&b){ map{|k,v| [b[k],v] }.to_h },
:mapv, ->(&b){ map{|k,v| [k,b[v]] }.to_h },
:maph, ->(&b){ to_a.map{|*q| b[*q] }.to_h },
:vals, ->(*q){ q.empty? ? values : values_at(*q) },
:flip, ->{ fold({}){|o,(k,v)| (o[v]||=[])<< k; o }},
:turn, ->{ fold({}){|o,(k,v)| v.hsh?&&v.fold(o){|o,(g,v)| (o[g]||={})[k]=v; o }||raise("value not a hash!") }},
:-, ->(o){ sift{|k,v| o.hsh? ? (o[k]!=v) : (!o.inc? k) }}
Hsh.aka :+=>:merge
Hsh.act :pair, ->(&b){ b||=->*q{q}; flat_map{|k,v| (v.ary? ? v : [v]).map{|v| b[k,v] } } }
Rng.act :[], ->(q){ (q > size) ? nil : (q >= 0) ? (first+q) : (last-q) },
:+, ->(q){ n,x=(q.rng? ? q.minmax : [q,q]); Rng(first+(n||0),last+(x||0),exclude_end?) },
:-, ->(q){ n,x=(q.rng? ? q.minmax : [q,q]); Rng(first-(n||0),last-(x||0),exclude_end?) },
:*, ->(q){ Rng(first*q, last*q,exclude_end?) if q.num? },
:/, ->(q){ Rng(first/q, last/q,exclude_end?) if q.num? },
:flip,->{ Rng(max||last,min||first) },
:clamp,->*q{ Rng(first.clamp(*q), last.clamp(*q),exclude_end?) }
Str.act :just,->(n,s=' '){ (n <= size) ? self : ((n-size)/2).lap{|q| (s*(n-size-q)) << self << (s*q) } },
:flags, ->q=nil,d=[nil],m='b*',&b{ r=unpack1(m).split('').indexes('1'); (q.nil? ? r.map(&b) : r.map{|i| (!d.inc?(q[i]))&&q[i]||i }).to_a },
:slices,->(*a,&b){ s,o=self,[]; (o << (b||->q{q})[s[0,a[0]||=size]]; s = s[a[0]..-1]||[]; a = a.rest if a.size>1) while s.ne?; o },
:b?, ->{ encoding.name == 'ASCII-8BIT' }, :b!, ->{ replace(b) }, :u, ->{ force_encoding('utf-8') },
:zeros, ->{ ("\x00"*bytesize).b }, :zeros!, ->{ replace(zeros) },
:vals, ->*q{ q.fmap{|q| self[q] } }
Str.aka flip: :reverse
TrueClass.act :to_i, ->{ 1 }
FalseClass.act :to_i, ->{ 0 }
Prc.act :wrap,->(*q,&b){ s=self; b.prc? ? ->(*a){ b[s,a,*q] } : s }
Prc::Nop = proc{}
Prc::Slf = proc{self}
Prc::Arg = proc{|*q|q}
if ![].act?(:repeated_permutation)
Ary.act :transpose, ->{ (s=map(&:size)).same? ? s[0].map{|i| map{|q| q[i] }} : raise("Arrays must be same length") },
:product, ->*q{ flat_map{|w| q.empty? ? [[w]] : q.head.product(*q.rest).map{|q| [w,*q] } }},
:permutation, ->(q=size){ nil }, :combination, ->q{ nil }, :repeated_combination, ->q{ nil }, :repeated_permutation, ->q{ nil }
end
Ary.aka turn: :transpose, perms: :permutation, repperms: :repeated_permutation, combs: :combination, repcombs: :repeated_combination
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment