2009-04-03 9 views
7
class Tree 
    def initialize*d;@d,=d;end 
    def to_s;@l||@r?",>":@d;end 
    def total;(@d.is_a?(Numeric)[email protected]:0)+(@[email protected]: 0)+(@[email protected]: 0);end 
    def insert d 
    alias g instance_variable_get 
    p=lambda{|s,o|d.to_s.send(o,@d.to_s)&& 
     (g(s).nil??instance_variable_set(s,Tree.new(d)):g(s).insert(d))} 
    @d?p[:@l,:]:@d=d 
    end 
end 

¿Alguien quiere dar un vistazo para explicar lo que hace? Apareció como una respuesta en una pregunta que hice sobre el código que es too clever. Pero es demasiado inteligente para mí decir si es simplemente una broma. Si no es así, me gustaría saber cómo funciona, en caso de que alguien se preocupe por explicarlo.Si este código no es una broma, ¿cómo funciona?

+0

nada en comparación con http://www.rubyinside.com/advent2006/4-ruby-obfuscation.html: P – Aziz

+0

@firoso: vuelva a slashdot si quiere troll un foro de TI. – Juliet

Respuesta

15

EDIT: La persona que publicó el ejemplo ofuscado originales dio the actual source code en su respuesta. También publicó un corrected version of the obfuscated code, porque como noté, algo de eso no tenía sentido incluso cuando eliminaba la sintaxis funky.

Ese es un código muy ofuscado. Al igual que con el código más ofuscado, en su mayoría son muchos operadores ternarios y un obstinado rechazo a poner espacios en blanco donde lo haría una persona normal. Aquí es básicamente la misma cosa por escrito de manera más normal:

class Tree 
    def initialize(*d) 
    @d, = d # the comma is for multiple return values, 
      # but since there's nothing after it, 
      # all but the first are discarded. 
    end 
    def to_s 
    @l || @r ? ",>" : @d 
    end 
    def total 
    total = @d.is_a?(Numeric) ? @d : 0 
    total += @l.total if @l 
    total += @r.total if @r 
    end 
    def insert(arg) 
    if @d 
     if @l 
     @l.insert(arg) 
     else 
     @l = Tree.new(arg) 
     end 
    else 
     @d = arg 
    end 
    end 
end 

El método de inserción no es válido sintácticamente (le falta un nombre de método en una parte), pero eso es básicamente lo que hace la medida de lo que puedo decir. La ofuscación en ese método es bastante grueso:

  1. En lugar de simplemente haciendo @l = whatever, utiliza instance_variable_get() y instance_variable_set(). Peor aún, alias instance_variable_get() para simplemente ser g().

  2. Cubre la mayor parte de la funcionalidad en una función lambda, a la que le pasa el nombre @l. Luego llama a esta función con la sintaxis menos conocida de func[arg1, arg2], que es equivalente a func.call(arg1, arg2).

9

Esto parece ser una implementación de árbol binario en muy pocas líneas. Me disculpo si mi comprensión de la sintaxis de rubí se limita:

class Tree     // defining the class Tree 

    def initialize *d;  // defines the initializer 
     @d = d;    // sets the node value 
    end 

    def to_s;     // defines the to_s(tring) function 
     @l || @r ? ",>" : @d; // conditional operator. Can't tell exactly what this 
           // function is intending. Would think it should make a 
           // recursive call or two if it's trying to do to_string 
    end 

    def total;    // defines the total (summation of all nodes) function 
     @d.is_a ? (Numeric) // conditional operator. Returns 
      ? @d    // @d if the data is numeric 
      : 0    // or zero 
     + (@l ? @l.total : 0) // plus the total for the left branch 
     + (@r ? @r.total : 0) // plus the total for the right branch 
    end 

    def insert d    // defines an insert function 
     ??     // but I'm not going to try to parse it...yuck 
    end 

la esperanza de que ayude a algunos ...:/

8

Empezó como esto:

class Tree 
    include Comparable 

    attr_reader :data 

    # Create a new node with one initial data element 
    def initialize(data=nil) 
    @data = data 
    end 

    # Spaceship operator. Comparable uses this to generate 
    # <, <=, ==, =>, >, and between? 
    def <=>(other) 
    @data.to_s <=> other.data.to_s 
    end 

    # Insert an object into the subtree including and under this Node. 
    # First choose whether to insert into the left or right subtree, 
    # then either create a new node or insert into the existing node at 
    # the head of that subtree. 
    def insert(data) 
    if [email protected] 
     @data = data 
    else 
     node = (data.to_s < @data.to_s) ? :@left : :@right 
     create_or_insert_node(node, data) 
    end 
    end 

    # Sum all the numerical values in this tree. If this data object is a 
    # descendant of Numeric, add @data to the sum, then descend into both subtrees. 
    def total 
    sum = 0 
    sum += @data if (@data.is_a? Numeric) 
    sum += [@left, @right].map{|e| e.total rescue 0}.inject(0){|a,v|a+v} 
    sum 
    end 

    # Convert this subtree to a String. 
    # Format is: <tt>\<data,left_subtree,right_subtree></tt>. 
    # Non-existant Nodes are printed as <tt>\<></tt>. 
    def to_s 
    subtree = lambda do |tree| 
     tree.to_s.empty? ? "<>" : tree 
    end 
    "<#{@data},#{subtree[@left]},#{subtree[@right]}>" 
    end 

    private ############################################################ 
    # Given a variable-as-symbol, insert data into the subtree incl. and under this node. 
    def create_or_insert_node(nodename, data) 
    if instance_variable_get(nodename).nil? 
     instance_variable_set(nodename, Tree.new(data)) 
    else 
     instance_variable_get(nodename).insert(data) 
    end 
    end 

end 

Creo que en realidad se rompió cuando estaba acortando hacia abajo. La versión de nueve líneas no funciona del todo. Me divertí independientemente. : P

Esta fue mi parte favorita:

def initialize*d;@d,=d;end 

Esto está haciendo uso de la asignación; fuimos paralelo para salvar un par de caracteres. Puede expandir esta línea a:

def initialize(*d) 
    @d = d[0] 
end 
+0

Juro cuando leí la publicación inicial que me preguntaba por qué la había visto antes. Luego recordé a un grupo de nosotros hablando cosas horribles que hacer para escribir la clase. –

+0

Haha, sí. Ohhh, 2150. – Burke

+0

Huh, me acabo de dar cuenta de que mi truco de asignación paralela es en realidad un personaje más largo que simplemente haciendo 'def initialize d; @ d = d; end'. Aunque es un poco más increíble, creo: P – Burke

7

He publicado el código original. Lo siento, pero no me molesté en comprobar que incluso lo hice bien, y un montón de cosas fueron eliminadas por menos de signos.

class Tree 
    def initialize*d;@d,=d;end 
    def to_s;@l||@r?"<#{@d},<#{@l}>,<#{@r}>>":@d;end 
    def total;(@d.is_a?(Numeric)[email protected]:0)+(@[email protected]: 0)+(@[email protected]: 0);end 
    def insert d 
    alias g instance_variable_get 
    p=lambda{|s,o|d.to_s.send(o,@d.to_s)&& 
     (g(s).nil??instance_variable_set(s,Tree.new(d)):g(s).insert(d))} 
    @d?p[:@l,:<]||p[:@r,:>]:@d=d 
    end 
end 

Así es como debería ser.

Cuestiones relacionadas