The Daily WTF: Curious Perversions in Information Technology
Welcome to TDWTF Forums Sign in | Join | Help
in Search

Speed Challenge 13: The Polygon Split

Last post 05-15-2007 8:20 AM by omega0. 9 replies.
Page 1 of 1 (10 items)
Sort Posts: Previous Next
  • 05-09-2007 3:04 PM

    Speed Challenge 13: The Polygon Split

    Sorry for the delay. Anyhow, let's get cracking:
    This time we're going to write a program that splits any surface into three- and four-sided polygons. The program should take a sequence of 2D coordinates as input, which should be linked together in a loop to define the surface. For simplicity's sake you may assume that the loop doesn't cross itself. The program can then split it any way it sees fit, as long as the end result consists only of three- and four-sided convex polygons. Obviously, the fewer polygons the better.
    How you choose to present the result is up to you, but it shouldn't be too hard to understand. You can also snag some bonus points with fancy ASCII or OpenGL graphics here.
    rpar PROTON all
  • 05-11-2007 8:43 AM In reply to

    Re: Speed Challenge 13: The Polygon Split

    I'll give you 12 hours as of this post. In the mean time, here's a simple solution that doesn't account for concave surfaces:
     
    # polysplit.py
    
    input_ = raw_input("Please enter the vertex coords in the format \"x,y\".\n")
    coords = []
    while input_:
        for xy in input_.split():
            coords.append(map(lambda x: int(x), xy.split(',')))
        input_ = raw_input()
    
    # Calculate which vertexes to link
    splits = []
    for i in range(2,len(coords)):
        splitindex = 2;
        while 1:
            if i % splitindex:
                break
            splits.append((i - splitindex, i)) 
            splitindex *= 2;
    
    print "Splits:"
    for line in splits:
        print "%d,%d -> %d,%d" % tuple(coords[line[0]] + coords[line[1]])
    
     
     
    rpar PROTON all
  • 05-13-2007 8:48 AM In reply to

    Re: Speed Challenge 13: The Polygon Split

     # poly.py

     def spdp(p1, p2, p3):
    """ return signum of perp dot product of edges p1..p2 and p2..p3 """
    x1, y1 = p1
    x2, y2 = p2
    x3, y3 = p3
    pdp = (y1 - y2)*(x3 - x2) + (x2 - x1)*(y3 - y2)
    if pdp < 0:
    return -1
    if pdp > 0:
    return 1
    return 0

    def isstrictlyconvex(pgon):
    N = len(pgon)
    if N < 3:
    return False
    signum1 = spdp(pgon[0], pgon[1], pgon[2])
    if signum1 == 0:
    return False
    if N == 3:
    return True
    for i in range(1, N):
    signum = spdp(pgon[i], pgon[(i + 1) % N], pgon[(i + 2) % N])
    if signum != signum1:
    return False
    return True

    input_ = raw_input('Enter vertices: ').split()
    pgon = []
    try:
    for pair in input_:
    x, y = pair.split(',')
    pgon.append((int(x), int(y)))
    except ValueError:
    print "No, no, no. You're supposed to enter the vertices as comma'ed pairs of integers."
    print "The pairs should be separated by whitespace. Example: -1,0 0,2 1,0 0,-2"
    else:
    if not isstrictlyconvex(pgon):
    print "What you supplied is not a (strictly) convex polygon."
    print "Maybe Faxmachinen has a better solution for you?"
    elif len(pgon) < 5:
    print "That's optimal as it is."
    else:
    x0, y0 = pgon[0]
    for i, (x, y) in enumerate(pgon[3:-1:2]):
    print '%d. Draw a line from %d,%d to %d,%d.' % (i + 1, x0, y0, x, y)
    print "That's it, well done!"

  • 05-13-2007 12:50 PM In reply to

    Re: Speed Challenge 13: The Polygon Split

    Good work. Speed Challenge 14 is all yours, Autonuke.
    rpar PROTON all
  • 05-13-2007 5:52 PM In reply to

    Speed Challenge 14: The New Ook!?

    You're lucky: in this challenge, you have the chance to dream up your very own programming language. But, before you go overboard to create the language that makes Python look ugly, you also have to write a program that can 1) translate programs in your new language into brainfuck, and 2) translate brainfuck programs into your new language.

    For example, I've just invented BabyTalk. It is as trivially isomorphic (well, nearly) with brainfuck as Ook! is. Here's an example:

    Ma! Ma? Ma. Ma. Ma. Ma! Ma? Ma? Ma? Ma? Ma ma ma ma ma. Ma ma ma ma. Ma? Ma. Ma. Ma. Ma! Ma? Ma! Ma ma ma ma. Ma. Ma! Ma? Ma! Ma? Ma! Ma! Ma? Ma! Ma? Ma ma ma ma? Ma. Ma. Ma! Ma ma ma ma. Ma! Ma ma ma? Ma ma ma! Ma ma ma! Ma ma ma? Ma ma! Ma ma ma ma ma ma! Ma ma ma ma. Ma? Ma! Ma ma ma ma ma ma ma ma! Ma ma ma ma? Ma! Ma ma ma ma ma ma ma ma. Ma? Ma? Ma! Ma? Ma! Ma? Ma. Ma ma ma ma ma ma ma ma! Ma ma ma ma ma ma ma ma? Ma. Ma! Ma? Ma ma ma ma ma ma ma ma. Ma ma ma ma? Ma. Ma! Ma ma ma ma ma ma ma ma? Ma ma ma! Ma ma ma. Ma. Ma! Ma? Ma? Ma? Ma! Ma. Ma! Ma! Ma. Ma! Ma? Ma. Ma. Ma! Ma ma ma ma ma ma ma ma! Ma ma ma ma. Ma ma ma ma ma ma ma ma! Ma! Ma? Ma. Ma ma ma ma ma ma ma ma! Ma ma? Ma ma? Ma ma! Ma ma? Ma ma? Ma ma? Ma ma ma ma ma ma ma ma. Ma ma. Ma ma. Ma ma! Ma ma! Ma ma! Ma ma! Ma ma? Ma ma? Ma ma ma ma ma ma ma ma! Ma ma ma ma? Ma. Ma ma ma ma ma ma ma ma? Ma ma ma ma? Ma ma ma ma ma ma ma ma.


    (The above prints 'Hello World!', a reasonable thing for a baby to say. Full stops, exclamation marks and question marks are interchangeable, to give the programmer that extra bit of poetic freedom.)

    The deadline is 24 hours from this post.
  • 05-14-2007 12:30 PM In reply to

    Re: Speed Challenge 14: The New Ook!?

    Evil pyramid schemes included:
    # pdcompiler.py
    
    # MUAHAHA!
    def opValue(script):
        if script and script[0] == "two":
            script.pop(0)
            if script and script[0] == "three":
                script.pop(0)
                if script and script[0] == "four":
                    script.pop(0)
                    return 8
                return 4
            return 2
        return 1
    
    def popTo(token, script):
        while script.pop(0) != token:
            if not script:
                print 'Error: Expected "%s", found EOF instead.' % token
                return False
        return True
    
    
    # Open files and read
    fname = raw_input("Please enter the Puppet Dance file to compile.\n")
    infile = open(fname, 'r')
    outfile = open(fname + '.b', 'w')
    script = infile.read().lower().split()
    infile.close()
    
    # Compile
    output = []
    token_num = 0
    error = False
    while script:
        token = script.pop(0)
        token_num += 1
    
        # Wishing Python had switch() right about now
        if token == "\o":
            if not popTo("o/", script):
                error = True
                break
        elif token == "o/":
            print 'Warning: Unexpected "o/" at token %d.' % token_num
        elif token == "one":
            opValue(script)  # Do nothing
        elif token == "up":
            output.append("+" * opValue(script))
        elif token == "down":
            output.append("-" * opValue(script))
        elif token == "left":
            output.append("<" * opValue(script))
        elif token == "right":
            output.append(">" * opValue(script))
        elif token == "go":
            output.append("[")
        elif token == "repeat":
            output.append("]")
        elif token == "jump":
            output.append(",>" * opValue(script))
        elif token == "spin":
            output.append(".>" * opValue(script))
        elif token == "two" or token == "three" or token == "four":
            print 'Error: Did not expect "%s" at %d.' % (token, token_num)
            error = True
            break
        else:
            print 'Error: Unknown token "%s" at %d.' % (token, token_num)
            error = True
            break
    
    if not error:
        # Optimize a little
        outstr = "".join(output).replace("><", "").replace("<>", "")
    
        # Write to output file
        outfile.write(outstr)
        print 'Compiled successfully to "%s.b"' % fname



    ----------------------------


    # pddecomp.py
    
    def repeat_count(element, array, index):
        result = 0
        while index < len(array) and array[index] == element:
            result += 1
            index += 1
        return result
    
    # Okay beating a dead horse here
    def multiop(num, op):
        result = []
        while num > 0:
            result.append(op)
            if num > 1:
                result.append("two")
                if num > 3:
                    result.append("three")
                    if num > 7:
                        result.append("four")
                        num -= 8
                    else:
                        num -= 4
                else:
                    num -= 2
            else:
                num -= 1
        return result
    
    # Open files and read
    fname = raw_input("Please enter the brainfuck file to decompile.\n")
    infile = open(fname, 'r')
    outfile = open(fname + '.pd', 'w')
    data = infile.read()
    infile.close()
    
    output = []
    i = 0
    while i < len(data):
        ch = data[i]
        rc = repeat_count(ch, data, i)
        if ch == '>':
            output += multiop(rc, "right")
            i += rc
        elif ch == '<':
            output += multiop(rc, "left")
            i += rc
        elif ch == '+':
            output += multiop(rc, "up")
            i += rc
        elif ch == '-':
            output += multiop(rc, "down")
            i += rc
        elif ch == ',':
            output += multiop(rc, "jump")
            i += rc
        elif ch == '.':
            output += multiop(rc, "spin")
            i += rc
        elif ch == '[':
            output.append("go")
            i += 1
        elif ch == ']':
            output.append("repeat")
            i += 1
    outfile.write(" ".join(output))
    outfile.close()
    print "Done."



    ----------------------------


    \o	hello.pd
    	Hello World in Puppet Dance	o/
    
    Right one two three  \o Note the cosmetic no-op o/
    Up two three four
    Go
    	Down left up two three four up
    	Right one two repeat
    Right two three
    Up two three four up two
    Go
    	Down left one two
    	Up two three four up two left
    	Up two three four up two left
    	Up two three four up two left
    	Up two three four up two left
    	Right two three right repeat
    
    Right one two three
    Up two three
    Go
    	Down left up two three four
    	Right one two repeat
    Right one two three
    Up two three up
    Go
    	Down left
    	Up two three four
    	Up two three four
    	Up one two
    	Right one two repeat
    Right two three
    Up two three four up two
    Go
    	Down left one two
    	Up two three four up two left
    	Up two three four up two left
    	Up two three four up two left
    	Up two three four up two left
    	Right two three right repeat
    
    Left one two three
    Left up two three four
    Left up two three four up two three up two
    Left up two three four up two up
    Left up two left
    Left up two three four up two up
    Left up two three four
    Left up two three four
    Left up left one two
    
    Go
    	Spin one two three repeat
    rpar PROTON all
  • 05-14-2007 2:46 PM In reply to

    Re: Speed Challenge 14: The New Ook!?

    Behold the horror of switch: the language with nothing but switch-case statements...

    to_switch.c

    #include 
    #include 
    #include 
    
    void parse_bf( int, int, int, char* );
    void indent( const char * );
    void indent_output( int );
    
    void fwd( int* );
    void rwd( int* );
    
    char code[2000];
    char output[1000];
    
    int id = 0;
    
    int main( int argc, char **argv )
    {
    	FILE * f;
    	int c;
    
    	int numi = 0;
    	int numo = 0;
    
    	int i = 0;
    	char data[1000] = {0};
    	
    	if( argc != 2 )
    	{
    		printf("Usage: %s filename\n", argv[0] );
    		exit(0);
    	}
    
    	f = fopen( argv[1], "r" );
    	while( !feof(f) )
    	{
    		c = getc( f );
    		code[i] = c;
    		if( c == '.' ) numo++;
    		i++;
    	}
    	fclose(f);
    	code[i] = 0;
    
    	if( numo == 0 )
    	{
    		exit(0);	// if there's no output, no need for any code
    	}
    
    	parse_bf( 0, 0, 0, data );
    }
    
    void parse_bf( int ip, int dp, int op, char *data )
    {
    	char *newdata = malloc( 1000 );
    	char c;
    	char s[20];
    	memcpy( newdata, data, 1000 );	// new copy of the data space
    
    	for(;code[ip];ip++)				// continue until end of code
    	{
    		switch(code[ip])			// normal brain fuck operators
    		{
    			case '+' :
    				newdata[dp]++;
    				break;
    			case '-' :
    				newdata[dp]--;
    				break;
    			case '>' :
    				dp = (dp+1) % 1000;
    				break;
    			case '<' :
    				dp--;
    				if( dp<0 ) dp+=1000;
    				break;
    			case '[' :
    				if( newdata[dp] == 0 )
    					fwd(&ip);			// branch foward
    				break;
    			case ']' :
    				if( newdata[dp] != 0 )
    					rwd(&ip);			// branch backward
    				break;
    			case '.' :
    				output[op] = newdata[dp];	// add to output buffer
    				op++;
    				break;
    			case ',' :
    				indent("switch {");		// possible change in execution here
    				id++;
    				// limited to kb chars
    				for(c=0x20;c<0x7F;c++)	// try all input chars
    				{
    					sprintf(s,"case %d",c);
    					indent(s);
    					newdata[dp] = c;
    					id++;
    					parse_bf( ip+1, dp, op, newdata );
    					indent("break");
    					id--;
    				}
    				id--;
    				indent("}");
    				free(newdata);
    				return;
    		}
    	}
    	indent_output(op);	// print output
    	free(newdata);		// clean up
    }
    
    void indent( const char *s )	// pretty up output
    {
    	int i;
    	for(i=0;i<id;i++)
    		printf("\t");
    	printf("%s\n",s );
    }
    
    void indent_output( int lim )
    {
    	int i,j;
    	for(i=0;i<lim;i++)
    	{
    		for(j=0;j<id;j++)
    			printf("\t");
    		printf("putc");
    		printf(" %d\n", output[i] );
    	}
    }
    
    void fwd( int *p )
    {
    	int cnt;
    	int q;
    
    	for(q=*p+1,cnt=1; cnt > 0; q++ )
    	{
    		if( code[q] == ']' )
    			cnt--;
    		if( code[q] == '[' )
    			cnt++;
    	}
    	*p = q;
    }
    
    void rwd( int *p )
    {
    	int cnt;
    	int q;
    
    	for(q=*p-1,cnt=1; cnt > 0; q-- )
    	{
    		if( code[q] == '[' )
    			cnt--;
    		if( code[q] == ']' )
    			cnt++;
    	}
    	*p = q;
    }
    

    from_switch.pl

    open( FILE, " )
    {
    	$line = $_;
    
    	if( $line =~ /putc (\d+)/ )
    	{
    		$char = $1;
    		print ">";							# get a clean cell
    		for($i=0;$i<$char;$i++)
    		{
    			print "+";						# generate the character
    		}
    		print ".[-]<\n";					# output and clear cell
    	}
    	elsif( $line =~ /switch/ )
    	{
    		print ",>\n";						# read in char
    	}
    	elsif( $line =~ /case (\d+)/ )
    	{
    		$num = $1;
    		print "<[->+>+<<]>>[-<<+>>]<\n";	# copy input to next cell
    		for($i=0;$i<$num;$i++)
    		{
    			print "-";						# will be zero if eqal
    		}
    		print "\n>+<[>-<[-]]>[-\n"			# branch if not equal
    	}
    	elsif( $line =~ /break/ )
    	{
    		print "]<\n";						# end branch
    	}
    }
    

    Switch behaves as follows:
    switch-case-break works similar to C, but switch uses the next char from stdin as its condition. putc outputs the following number as a char

    For example, Hello World is implemented via this switch code: putc 72 putc 101 putc 108 putc 108 putc 111 putc 32 putc 87 putc 111 putc 114 putc 108 putc 100 putc 33 putc 10 (Just in case I missed an < to escape, the source files are also: http://omega0.xepher.net/stuff/to_switch.c http://omega0.xepher.net/stuff/from_switch.pl )
  • 05-14-2007 3:17 PM In reply to

    Re: Speed Challenge 14: The New Ook!?

    I almost forgot the documentation:
     
    Puppet Dance - A brief reference
     

    Overview:
    ---------
    The Puppet Dance compiler converts Puppet Dance code into brainfuck code. As such, brainfuck conditions apply. Standard brainfuck intitializes a 30.000 array of single-byte cells, and places the cell pointer in the first cell.
     
    Puppet Dance separates statements by whitespace. Spaces, tabs and newlines all count as whitespace.
     

    Reference:
    ----------
     
     \o [<comment>] o/
    A comment block starts with "\o" and ends with "o/". Comments can span multiple lines.
     
     one[ two[ three[ four]]]
    No-op.
     
     up[ two[ three[ four]]]
    Increase current cell by (2^n) where n is number of optional parameters.
     
     down[ two[ three[ four]]]
    Decrease current cell by (2^n).
     
     left[ two[ three[ four]]]
    Move cell pointer back (2^n).
     
     right[ two[ three[ four]]]
    Move cell pointer forwards (2^n).
     
     go <...> repeat
    Loops <...> until the cell pointed to at the start of the loop is 0. Note that if the cell starts out 0, the loop is never executed.
     
     jump[ two[ three[ four]]]
    Inserts (2^n) characters from the input stream to the current pointer location. The pointer moves forwards (2^n).
     
     spin[ two[ three[ four]]]
    Writes (2^n) characters from the current pointer location to the output stream. The pointer moves forwards (2^n).
    rpar PROTON all
  • 05-14-2007 7:28 PM In reply to

    Re: Speed Challenge 14: The New Ook!?

    Thank you both for your submissions.

    Faxmachinen: Puppet Dance has much to recommend it - the cosmetic no-op, the comment markers and the pyramid scheme. I also like how easy it is to re-use code, e.g. to entertain a children's birthday party.

    omega0: now that's purely evil. I especially like how you emulate a brainfuck program in order to compile it. Your turn.



  • 05-15-2007 8:20 AM In reply to

    Re: Speed Challenge 14: The New Ook!?

Page 1 of 1 (10 items)
Powered by Community Server (Non-Commercial Edition), by Telligent Systems