Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Triforce Programming Challenge

Credits go to axilmar, Bruce Perry, Dustin Howett, kazzmir, machine, Martin Kalbfuß, Matthew Leverton, Peter Wang, and Xuzzers for helping out!
This thread is locked; no one can reply to it. rss feed Print
 1   2 
Triforce Programming Challenge
Kibiz0r
Member #6,203
September 2005
avatar

My internet friend had an interesting assignment for his programming midterm, so I thought I'd share it with you guys and see how creative we can get with our solutions.

Use whatever language you like; cookies for participants. :)

The Problem

Assume the user gives you a numeric input ranging from 1 to 7.

When the input is 1, print the following:

***********
 *********
  *******
   *****
    ***
     *

Values greater than one should generate multiples of the pattern, ending with the one above, but always stacked symmetrically.

For example, 3 should print the following:

*********** *********** ***********
 *********   *********   ********* 
  *******     *******     *******  
   *****       *****       *****   
    ***         ***         ***    
     *           *           *     
      *********** ***********
       *********   ********* 
        *******     *******  
         *****       *****   
          ***         ***    
           *           *     
            ***********
             ********* 
              *******  
               *****   
                ***    
                 *     

For bonus points, also print the reverse:

*********** *********** ***********
 *********   *********   ********* 
  *******     *******     *******  
   *****       *****       *****   
    ***         ***         ***    
     *           *           *     
      *********** ***********
       *********   ********* 
        *******     *******  
         *****       *****   
          ***         ***    
           *           *     
            ***********
             ********* 
              *******  
               *****   
                ***    
                 *     
                 *     
                ***    
               *****   
              *******  
             ********* 
            ***********
           *           *     
          ***         ***    
         *****       *****   
        *******     *******  
       *********   ********* 
      *********** ***********
     *           *           *     
    ***         ***         ***    
   *****       *****       *****   
  *******     *******     *******  
 *********   *********   ********* 
*********** *********** ***********

My Solution

I used C#. I wrote the tests first, as I do with most programming tasks, especially those with detailed data manipulation. The first pass was completely imperative, with a ton of loops and counters all shoving stuff into a buffer, but once I had something working I boiled it down to its essence and LINQified it.

Source code below.

Program.cs#SelectExpand
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace ConsoleApplication1 7{ 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 Console.WriteLine("Welcome, Hero of Time"); 13 Console.WriteLine("How many triforces?"); 14 var iterations = Int32.Parse(Console.ReadLine()); 15 Console.WriteLine("Do you want to reverse them as well?"); 16 var reverse = Boolean.Parse(Console.ReadLine()); 17 Console.WriteLine(Triforce.MakeTriforce(iterations, reverse)); 18 Console.ReadKey(true); 19 } 20 } 21}

Triforce.cs#SelectExpand
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5 6namespace ConsoleApplication1 7{ 8 public static class Triforce 9 { 10 private static IEnumerable<string> makeTriforceIteration(int buffer, int iteration) 11 { 12 var triforce = @"*********** 13 ********* 14 ******* 15 ***** 16 *** 17 * "; 18 var bufferString = String.Join("", Enumerable.Repeat(" ", buffer)); 19 return from line in triforce.Split(new string[] { Environment.NewLine }, StringSplitOptions.None) 20 select bufferString + String.Join(" ", Enumerable.Repeat(line, iteration)); 21 } 22 23 public static string MakeTriforce(int iterations, bool reverse) 24 { 25 var result = (from buffer in Enumerable.Range(0, iterations) 26 let iteration = iterations - buffer 27 select makeTriforceIteration(buffer, iteration)).SelectMany(s => s); 28 if (reverse) 29 { 30 result = result.Concat(result.Reverse()); 31 } 32 return String.Join(Environment.NewLine, result); 33 } 34 } 35}

TriforceTest.cs#SelectExpand
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Text; 5using NUnit.Framework; 6 7namespace ConsoleApplication1 8{ 9 [TestFixture] 10 public class TriforceTest 11 { 12 [Test] 13 public void ProducesASingleTriforceWhenInputIs1() 14 { 15 var singleTriforce = @"*********** 16 ********* 17 ******* 18 ***** 19 *** 20 * "; 21 Assert.That(Triforce.MakeTriforce(1, false), Is.EqualTo(singleTriforce)); 22 } 23 24 [Test] 25 public void ProducesTwoTrifocesWhenInputIs2() 26 { 27 var doubleTriforce = @"*********** *********** 28 ********* ********* 29 ******* ******* 30 ***** ***** 31 *** *** 32 * * 33 *********** 34 ********* 35 ******* 36 ***** 37 *** 38 * "; 39 Assert.That(Triforce.MakeTriforce(2, false), Is.EqualTo(doubleTriforce)); 40 } 41 42 [Test] 43 public void ProducesThreeTrifocesWhenInputIs3() 44 { 45 var tripleTriforce = @"*********** *********** *********** 46 ********* ********* ********* 47 ******* ******* ******* 48 ***** ***** ***** 49 *** *** *** 50 * * * 51 *********** *********** 52 ********* ********* 53 ******* ******* 54 ***** ***** 55 *** *** 56 * * 57 *********** 58 ********* 59 ******* 60 ***** 61 *** 62 * "; 63 Assert.That(Triforce.MakeTriforce(3, false), Is.EqualTo(tripleTriforce)); 64 } 65 66 [Test] 67 public void ProducesReverse() 68 { 69 var reverseTriforce = @"*********** *********** *********** 70 ********* ********* ********* 71 ******* ******* ******* 72 ***** ***** ***** 73 *** *** *** 74 * * * 75 *********** *********** 76 ********* ********* 77 ******* ******* 78 ***** ***** 79 *** *** 80 * * 81 *********** 82 ********* 83 ******* 84 ***** 85 *** 86 * 87 * 88 *** 89 ***** 90 ******* 91 ********* 92 *********** 93 * * 94 *** *** 95 ***** ***** 96 ******* ******* 97 ********* ********* 98 *********** *********** 99 * * * 100 *** *** *** 101 ***** ***** ***** 102 ******* ******* ******* 103 ********* ********* ********* 104*********** *********** ***********"; 105 Assert.That(Triforce.MakeTriforce(3, true), Is.EqualTo(reverseTriforce)); 106 } 107 } 108}

Matthew Leverton
Supreme Loser
January 1999
avatar

#SelectExpand
1<?php 2 ($t = $argc > 1 ? intval($argv[1]) : 3) > 0 or die("enter count > 0\n"); 3 ($A = $argc > 2 ? intval($argv[2]) | 1 : 11) > 0 or die("enter size > 0\n"); 4 $B = ($A + 1) / 2; 5 6 ob_start(); 7 do 8 { 9 for ($z = 0; $z < $B; ++$z) 10 { 11 echo str_repeat(' ', $s); 12 for ($y = 0; $y < $t; ++$y) echo str_repeat(' ', $z).str_repeat('*', $A-($z*2)).str_repeat(' ', $z+1); 13 echo "\n"; 14 } 15 $s += $B; 16 } 17 while (--$t); 18 echo rtrim($b = ob_get_clean()); 19 20 foreach (array_reverse(explode("\n", $b)) as $l) echo "$l\n"; 21?>

Edit: added second parameter.

./triforce.php [count [size]]

Dustin Dettmer
Member #3,935
October 2003
avatar

trap15
Member #11,752
March 2010

Wrote this one in C, my usual choice for everything. Thought of using python, but meh.
Does the inverse one as well :)

#SelectExpand
1#include <stdio.h> 2 3void print_chunk(char string[], int count, int starts) 4{ 5 int i; 6 for(i = 0; i < starts; i++) 7 printf(" "); 8 for(i = 0; i < count; i++) 9 printf("%s", string); 10 printf("\n"); 11} 12 13void print_triforce_strip(int count, int start, int dir) 14{ 15 if(dir == 0) { 16 print_chunk("*********** ", count, start); 17 print_chunk(" ********* ", count, start); 18 print_chunk(" ******* ", count, start); 19 print_chunk(" ***** ", count, start); 20 print_chunk(" *** ", count, start); 21 print_chunk(" * ", count, start); 22 }else{ 23 print_chunk(" * ", count, start); 24 print_chunk(" *** ", count, start); 25 print_chunk(" ***** ", count, start); 26 print_chunk(" ******* ", count, start); 27 print_chunk(" ********* ", count, start); 28 print_chunk("*********** ", count, start); 29 } 30} 31 32int main(int argc, char *argv[]) 33{ 34 int i; 35 int c = atoi(argv[1]); 36 for(i = 0; i < c; i++) { 37 print_triforce_strip(c - i, i, 0); 38 } 39 for(i = 0; i < c; i++) { 40 print_triforce_strip(i + 1, c - i - 1, 1); 41 } 42 return 0; 43}

Matthew Leverton
Supreme Loser
January 1999
avatar

I like this version better:

#SelectExpand
1<?php 2 ($t = $argc > 1 ? intval($argv[1]) : 3) > 0 or die("enter count > 0\n"); 3 ($A = $argc > 2 ? intval($argv[2]) | 1 : 11) > 0 or die("enter size > 0\n"); 4 $B = ($A + 1) / 2; 5 6 for ($j = 0, $b = ''; $j < $t; ++$j) 7 { 8 $l = str_repeat(' ',$j * $B).str_repeat(' '.str_repeat('*', $A), $t-$j). ' '; 9 for ($i = 0; $i < $B; ++$i, $l = strtr($l, array(" *"=>" ", "* *" => " ", "* "=>" "))) 10 $b .= "$l\n"; 11 } 12 13 echo rtrim($b).implode("\n", array_reverse(explode("\n", $b)))."\n"; 14?>

trap15
Member #11,752
March 2010

Anyone gonna make a 1-liner Perl script to do it? :-X

kazzmir
Member #1,786
December 2001
avatar

Mine is in python and uses combinators. Not the shortest..

#SelectExpand
1#!/usr/bin/env python 2 3def reverse(l): 4 return l[::-1] 5 6class Triangle: 7 def __init__(self, height = 7): 8 self.height = height 9 10 def lines(self, pixel = '*'): 11 for length in range(self.height - 1, 0, -1): 12 yield ' ' * (self.height - length - 1) + pixel * (length * 2 - 1) + ' ' * (self.height - length) 13 14class Printer: 15 def __init__(self, triangle): 16 self.triangle = triangle 17 18 def show(self): 19 for line in self.triangle.lines(): 20 yield line 21 22class CombinePrinter(Printer): 23 def __init__(self, p1, p2): 24 self.p1 = p1 25 self.p2 = p2 26 27 def show(self): 28 s1 = self.p1.show() 29 s2 = self.p2.show() 30 while True: 31 try: 32 yield s1.next() + s2.next() 33 except StopIteration: 34 break 35 36class SequencePrinter(Printer): 37 def __init__(self, printer1, printer2): 38 self.printer1 = printer1 39 self.printer2 = printer2 40 41 def show(self): 42 s1 = self.printer1.show() 43 s2 = self.printer2.show() 44 while True: 45 try: 46 yield s1.next() 47 except StopIteration: 48 break 49 while True: 50 try: 51 yield s2.next() 52 except StopIteration: 53 break 54 55class SpacePrinter(Printer): 56 def __init__(self, printer, space): 57 self.printer = printer 58 self.space = space 59 60 def show(self): 61 s1 = self.printer.show() 62 while True: 63 try: 64 yield " " * self.space + s1.next() 65 # yield s1.next() 66 except StopIteration: 67 break 68 69class ReversePrinter(Printer): 70 def __init__(self, printer): 71 self.printer = printer 72 73 def show(self): 74 out = reverse([line for line in self.printer.show()]) 75 for line in out: 76 yield line 77 78def printN(num): 79 all = [Printer(Triangle()) for x in xrange(0, num)] 80 return reduce(lambda a, b: CombinePrinter(a, b), all) 81 82def triforce(height): 83 all = [SpacePrinter(printN(total), (height - total - 1) * 6) for total in xrange(1, height)] 84 return reduce(lambda a, b: SequencePrinter(b, a), all) 85 86def printit(printer): 87 for line in printer.show(): 88 print line 89 90# Printer().show(Triangle()) 91# printit(CombinePrinter(CombinePrinter(Printer(Triangle()), Printer(Triangle())), Printer(Triangle()))) 92# printit(printN(5)) 93# printit(SequencePrinter(printN(5), SpacePrinter(printN(4), 6))) 94def doit(n): 95 printit(SequencePrinter(triforce(n), ReversePrinter(triforce(n)))) 96 97import sys 98doit(int(sys.argv[1]))

Xuzzers
Member #11,753
March 2010

New user here.

My four-line solution in Python 2 (or 3?), doesn't do the reverse:

def triforce(num):
  for i in range(num - 1, -1, -1):
    for x in range(5, -1, -1):
      print (' ' * (6 * (num - 1 - i))) + ' '.join(('%s%s%s' % (' ' * (5 - x), '*' * ((2 * x) + 1), ' ' * (5 - x)) for m in range(0, i + 1)))
      
triforce(int(input()))

Not sure how to do the fancy code tags, but that works, I guess :).

Edit: fixed.

Kibiz0r
Member #6,203
September 2005
avatar

The bar has been raised!

This is my most compact solution, using a string extension for String.Repeat().
Edit: Removed prompts.

#SelectExpand
1using System; 2using System.Linq; 3 4namespace ConsoleApplication1 5{ 6 class Program 7 { 8 static void Main(string[] args) 9 { 10 var iterations = Int32.Parse(Console.ReadLine()); 11 var reverse = Boolean.Parse(Console.ReadLine()); 12 var triforce = from i in Enumerable.Range(0, iterations) 13 from j in Enumerable.Range(0, 6) 14 select " ".Repeat(6 * i) + (" ".Repeat(j) + "*".Repeat(11 - j * 2) + " ".Repeat(j + 1)).Repeat(iterations - i); 15 Console.WriteLine(reverse ? String.Join(Environment.NewLine, triforce.Concat(triforce.Reverse())) : String.Join(Environment.NewLine, triforce)); 16 } 17 } 18}

Xuzzers
Member #11,753
March 2010

Now, what does that say about Python and C# ;P.

Kibiz0r
Member #6,203
September 2005
avatar

They both let you take the long way or the short way?

Thomas Fjellstrom
Member #476
June 2000
avatar

n/m

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"Goto is the buldozer of coding. Sometimes, the buldozer is just the right tool for the job. Not often, but sometimes." -- LordBob

Dustin Howett
Member #11,754
March 2010

Perl one-liner, does not do reverse. Takes a single argument on the commandline.

#SelectExpand
1map { print "".(" " x (6*int($_/6))), ((" " x ($_%6)).("*" x (11-2*($_%6))).(" " x ($_%6))." ") x ($ARGV[0]-int($_/6)), "\n"; } ((0 .. (6*$ARGV[0])-1));

(EDIT: The following prints it reversed as well.

#SelectExpand
1map { print "".(" " x (6*int($_/6))), ((" " x ($_%6)).("*" x (11-2*($_%6))).(" " x ($_%6))." ") x ($ARGV[0]-int($_/6)), "\n"; } ((0 .. (6*$ARGV[0])-1), reverse(0 .. ((6*$ARGV[0])-1)));

)

Can be run as:

/usr/bin/perl -e 'map { print "".(" " x (6*int($_/6))), ((" " x ($_%6)).("*" x (11-2*($_%6))).(" " x ($_%6))." ") x ($ARGV[0]-int($_/6)), "\n"; } ((0 .. (6*$ARGV[0])-1));' 3

Peter Wang
Member #23
April 2000

... What?

#SelectExpand
1#include <stdio.h> 2#include <stdlib.h> 3 4char *tri[] = { 5"***********", 6" ********* ", 7" ******* ", 8" ***** ", 9" *** ", 10" * "}; 11 12int main(int argc, char *argv[]) 13{ 14 int h = atoi(argv[1]); 15 int x, y, w; 16 for (w = h; w > 0; w--) { 17 for (y = 0; y < 6; y++) { 18 for (x = 0; x < (h - w) * 6; x++) 19 putchar(' '); 20 for (x = 0; x < w - 1; x++) 21 printf("%s ", tri[y]); 22 printf("%s\n", tri[y]); 23 } 24 } 25 for (w = 1; w <= h; w++) { 26 for (y = 5; y >= 0; y--) { 27 for (x = 0; x < (h - w) * 6; x++) 28 putchar(' '); 29 for (x = 0; x < w - 1; x++) 30 printf("%s ", tri[y]); 31 printf("%s\n", tri[y]); 32 } 33 } 34 return 0; 35}

Kibiz0r
Member #6,203
September 2005
avatar

Xuzzers said:

Now, what does that say about Python and C# ;P.

Modded my solution to look slightly more like yours*, just because it looks eerily similar for two languages you probably wouldn't place next to each other at the dinner table.

*Looks almost exactly the same if you run it through a C# interpreter to avoid the boilerplate stuff!

I'll try a Ruby solution tomorrow if I feel like it.

Dustin Dettmer
Member #3,935
October 2003
avatar

Obligatory whitespace solution.

(Only 7 lines)

Peter Wang
Member #23
April 2000

Haskell:

#SelectExpand
1go n = do 2 mapM putStr $ map unlines $ reverse $ map reverse $ rows n 3 mapM putStr $ map unlines $ rows n 4 5rows n = [padrow (n-i) (row i) | i <- [1..n]] 6 7padrow w = map (sp ++) 8 where sp = replicate (6*w) ' ' 9 10row 1 = tri 11row n = zipWith join tri (row (n-1)) 12 13join x y = x ++ " " ++ y 14 15tri = map line [1..6] 16 17line n = sp ++ replicate (n*2-1) '*' ++ sp 18 where sp = replicate (6-n) ' '

axilmar
Member #1,204
April 2001

c++:

#SelectExpand
1#include <iostream> 2using namespace std; 3 4int main() { 5 cout << "input triforce number: "; 6 int n; 7 cin >> n; 8 for(int t = n; t > 0; --t) { 9 for(int i = 11; i >= 1; i -= 2) { 10 for(int j = 0; j < (n-t)*12/2; ++j) cout << " "; 11 for(int k = 0; k < t; ++k) { 12 for(int j = 0; j < 11/2 - i/2; ++j) cout << " "; 13 for(int j = 0; j < i ; ++j) cout << "*"; 14 for(int j = 0; j < 12/2 - i/2; ++j) cout << " "; 15 } 16 cout << endl; 17 } 18 } 19 return 0; 20}

Xuzzers
Member #11,753
March 2010

One line of Python:

print('\n'.join('\n'.join(((' ' * (6 * n)) + ' '.join(('%s%s%s' % (' ' * (5 - x), '*' * ((2 * x) + 1), ' ' * (5 - x)) for m in range(i + 1)))) for x in range(5, -1, -1)) for n, i in enumerate(range(int(input()) - 1, -1, -1))))

Doesn't print the reverse, at least yet ::)

Edit: Online! The stuff with input() is to fake it when there is no input() allowed. http://codepad.org/ZwE4KsP3

Dustin Dettmer
Member #3,935
October 2003
avatar

#SelectExpand
1#include <iostream> 2using namespace std; 3 4int main() { 5 cout << "input triforce number: "; 6 int n; 7 cin >> n; 8 for(int t = n; t > 0; --t) { 9 for(int i = 11; i >= 1; i -= 2) { 10 cout << string((n-t)*12/2, ' '); 11 for(int k = 0; k < t; ++k) { 12 cout << string(11/2 - i/2, ' '); 13 cout << string(i, '*'); 14 cout << string(12/2 - i/2, ' '); 15 } 16 cout << endl; 17 } 18 } 19}

X-G
Member #856
December 2000
avatar

All I keep thinking is newfags can't triforce.

--
Since 2008-Jun-18, democracy in Sweden is dead. | 悪霊退散!悪霊退散!怨霊、物の怪、困った時は ドーマン!セーマン!ドーマン!セーマン! 直ぐに呼びましょう陰陽師レッツゴー!

axilmar
Member #1,204
April 2001

#SelectExpand
1#include <iostream> 2#include <string> 3using namespace std; 4 5template <class T> T repeat(int times, const T &t) { return times > 0 ? t + repeat(times - 1, t) : T(); } 6 7int main() { 8 cout << "input triforce number: "; 9 int n; 10 cin >> n; 11 for(int t = n; t > 0; --t) { 12 for(int i = 11; i >= 1; i -= 2) { 13 cout << string((n-t)*6, ' ') << repeat(t, string(5 - i/2, ' ')+string(i,'*')+string(6 - i/2, ' ')) << "\n"; 14 } 15 } 16}

Arthur Kalliokoski
Second in Command
February 2005
avatar

Quote:

newfags can't triforce [knowyourmeme.com].

Well, truth be told, I seen the original post about 1 hour after it started, and began working on a plain old C implementation. About 15 minutes after that, I saw the "Now, what does that say about Python and C#" quote, and was somewhat flummoxed. Anyway, during the course of this I was informed that I no longer had a job, which torqued my gourd for quite a few hours, so I gave up entirely. But in the end, there have been a few posts well beyond what I'm capable of, so kudos to you ;D. Other subjects and areas of interest notwithstanding of course...

We would be a lot safer if the Government would take its money out of science and put it into astrology and the reading of palms. Only in superstition is there hope. If you want to become a friend of civilization, then become an enemy of the truth and a fanatic for harmless balderdash. — Kurt Vonnegut

LennyLen
Member #5,313
December 2004
avatar

I seen the original post

You what?

Sirocco
Member #88
April 2000
avatar

Load "triforce",8,1
Run

-->
Graphic file formats used to fascinate me, but now I find them rather satanic.

 1   2 


Go to: