Generate a right triangle

10

1

In this challenge, you must take two numbers (separated by a space) as input and output an ASCII right triangle, made up of xs.

The first number will be the width and height of the triangle you should output. The second number will be which corner the right angle will be in. The corners are numbered 1 to 4, starting in the top left and going in English reading order:

1    2



3    4

For example (inputs and their respective triangle outputs):

INPUT | 3 1 | 3 2 | 3 3 | 3 4
------+-----+-----+-----+----
 OUT- | xxx | xxx | x   |   x
 PUT  | xx  |  xx | xx  |  xx
      | x   |   x | xxx | xxx

Your program's output must match these examples exactly for their respective inputs.

The input will always be valid: the first number will be an integer ≥1, and the second number will be 1, 2, 3, or 4.

This is ; shortest code (in character count) wins.

Doorknob

Posted 2013-08-23T23:45:09.973

Reputation: 68 138

Answers

9

APL (30)

{' x'[1+(⍎⍵⌷'⌽+⍉⊖')≤/¨⍳2⍴⍺]}/⎕

Explanation:

  • {...}/⎕: reduce given function over the input (so if the input has 2 numbers, just calls the function with those two numbers, being the left number and the right number)
  • ≤/¨⍳2⍴⍺: Make an -by- coordinate matrix and set those positions where the X coordinate is not greater than the Y coordinate, giving a bitfield.
  • (⍎⍵⌷'⌽+⍉⊖'): select a transformation function given by to put the triangle right-side-up.
  • ' x'[1+...]: add one to the bitfield, and use the result as an index into the string ' x', so putting space for 0 and x for 1.

marinus

Posted 2013-08-23T23:45:09.973

Reputation: 30 224

1The more APL I read, the more I realize APL is a parsing nightmare. Wouldn't it have to actually evaluate the (⍎⍵⌷'functions') part before it decides how to interpret the whole statement? Consider for example 1+(⍵⌷'12+')|40. It wouldn't even know if | is monadic or dyadic before ing that parenthesized portion.

The whole abstract syntax tree changes depending on the evaluation. – protist – 2013-11-20T12:13:36.127

I meant 1+(⍎⍵⌷'12+')|40...will not let me edit. – protist – 2013-11-20T12:58:52.723

2

@protist: Fun fact: f ← { [ } does not give an error! f 1÷0 gives... a domain error! (because of the division by zero). Only when you call the function like f 123 you get syntax error. Behold: http://imgur.com/jtmdi4B

– marinus – 2013-11-20T18:11:47.803

By all the gods!!!! That breaks my heart a little. I have been playing with writing APL interpreters some, and that demonstrates a great evil in the current implementations. hahaha – protist – 2013-11-20T18:59:10.167

It almost seems like functions are put in place routinely by some sort of ugly macro-expansion-like process. It would somewhat indicate in-place text expansion. – protist – 2013-11-20T19:00:44.863

@protist: Yeah, I was rather surprised too when I discovered that the ⍎⍵⌷ thing works. When I wrote this, I thought J-style gerunds would come in very handy and on a whim I tried this. Luckily I don't actually use APL for any "real" programming. The way it works, it's actually impossible to parse a function without knowing what its formal parameters are - so that means it actually has to reparse the function every time you call it! – marinus – 2013-11-20T19:43:26.490

@protist: This of course is mitigated by the fact that this only holds for functions that contain , and those would have to do parsing on each call anyway. Though considering { [ } is not a syntax error I don't think it actually does that optimization. – marinus – 2013-11-20T19:50:21.887

6

Ruby, 116 115 109 96

I shall start with my own solution.

i=gets.split
s=i[0].to_i
(i[1]<?3?s.downto(1):1..s).map{|x|t=?x*x
puts /2|4/=~i[1]?t.rjust(s):t}

I just know that I'll get beat by a 30 character GolfScript solution almost instantly :P

Thanks to minitech for shaving off 19 characters (wow)!

Doorknob

Posted 2013-08-23T23:45:09.973

Reputation: 68 138

Instead of ==0, you can use <1. ?x*x saves another character. Also, puts i[1]%2<1?t.rjust(s):t} would do the trick, right? – Ry- – 2013-08-25T00:31:41.300

Hmm… you have spaces around the ?? Is that necessary? Also, I think you can do the same thing with the r=. – Ry- – 2013-08-25T03:55:16.760

@minitech It is necessary - the leading space because otherwise it parses 1? as a single token, and the trailing space because otherwise it parses as ?t (which is equivalent to 't'). How do you propose restructuring the r part? – Doorknob – 2013-08-25T14:07:20.967

Did you try it? Under which version of Ruby? Works fine for me on 2.0. – Ry- – 2013-08-25T14:12:54.077

@minitech Odd, it didn't work before and now it does :P Thanks – Doorknob – 2013-08-25T14:15:30.843

You can get it down to 99: https://gist.github.com/minitech/6334130

– Ry- – 2013-08-25T14:30:28.587

@minitech Wow, thanks! You're amazing at code golf :P – Doorknob – 2013-08-25T14:32:19.213

Oops, and of course one more with .map &:to_i :D Also, thanks! – Ry- – 2013-08-25T14:36:21.193

Keep it as a string and abuse ord to shave off… one more character: https://gist.github.com/minitech/6334130/revisions

– Ry- – 2013-08-25T14:45:36.537

Regular expressions for… one more! puts /2|4/=~i[1]?… – Ry- – 2013-08-25T15:04:52.137

4

GolfScript (34 33 chars)

~\:^,{)' x'^*$>^<0(2$?%}%\(2&(%n*

It's a shame that the corners aren't numbered in rotation, because that would allow a more elegant approach of building one array and then rotating it n times:

~\:^,{)' x'^*$>^<}%{-1%zip}@)*n*

Peter Taylor

Posted 2013-08-23T23:45:09.973

Reputation: 41 901

3

C# - 195

using System;class P{static void Main(string[]a){int G=int.Parse(
a[0]),O=int.Parse(a[1]),L=O<3?0:G+1,F=O<3?-G:1;G=O%2>0?-G:G;for(;
F<L;F++)Console.Write("{0,"+G+"}\n","".PadRight(F<0?-F:F,'x'));}}

Formatted:

using System;
class P
{
    static void Main(string[] a)
    {
        int G = int.Parse(a[0]),
            O = int.Parse(a[1]),
            L = O < 3 ? 0 : G + 1,
            F = O < 3 ? -G : 1;

        G = O % 2 > 0 ? -G : G;

        for(; F < L; F++)
            Console.Write("{0," + G + "}\n", "".PadRight(F < 0 ? -F : F, 'x'));
    }
}

enter image description here

Igby Largeman

Posted 2013-08-23T23:45:09.973

Reputation: 353

Input has to be space-delimited, not comma separated. – Doorknob – 2013-08-24T13:13:04.647

@Doorknob: The screenshot is from a test program where I chose to show the input with a comma. The input actually is space delimited when you execute the program, although the point is moot because all C# console applications receive input as an array of strings. – Igby Largeman – 2013-08-25T06:48:57.467

2

Mathematica 122 (104?)

g@s_ := ({w, p} = ToExpression@StringSplit@s; 
   Array[If[Switch[p, 1, # <= (w + 1 - #2), 2, # <= #2, 3, # >= #2, 4, # > (w - #2)],
   "X", ""] &, {w, w}]) // Grid

GraphicsGrid[{{g["12 1"], g["12 3"]}}]

another method


Under a liberal interpretation of "output", the following (104 chars) will work.

f@s_ := ({w, p} = ToExpression@StringSplit@s; 
  Graphics[Polygon@Delete[{{w, 0}, {0, 0}, {w, w}, {0, w}}, p], Axes -> True])


f["50 4"]

triangle


If input in the form of a list were permitted, the following (75 chars) would suffice:

f[{w_, p_}] := 
 Graphics[Polygon@Delete[{{w, 0}, {0, 0}, {w, w}, {0, w}}, p], Axes -> True]

DavidC

Posted 2013-08-23T23:45:09.973

Reputation: 24 524

Technically this is against the rules :P – Doorknob – 2013-08-24T04:58:16.677

What rule does it violate? – DavidC – 2013-08-24T04:58:54.577

The input/output chart thingy I put. The 122 char one is good though. I edited the question to clarify – Doorknob – 2013-08-24T04:59:24.107

Oops. I thought the chart was simply an example. – DavidC – 2013-08-24T05:00:57.253

I just placed the ASCII art version in first place. – DavidC – 2013-08-24T11:15:20.540

2

Golfscript, 39 36 35 characters

~\:y,{' '*'x'y*+y<0~2$?%}%-1@2>?%n*

live demo: http://golfscript.apphb.com/?c=OyczIDInCn5cOnkseycgJyoneCd5Kit5PC0xIDIkPyV9JS0xQDI%2BPyVuKgo%3D

too bad it's not 30 characters as requested

John Dvorak

Posted 2013-08-23T23:45:09.973

Reputation: 9 048

Replacing 1${-1%}* with -1 2$?% and \2>{-1%}* with \2>-1\?% will net you 2 characters. – Volatility – 2013-08-24T09:54:08.237

@Volatility thanks, incorporated – John Dvorak – 2013-08-24T10:12:26.870

@Volatility -1 2 can be written 0~2 – Howard – 2013-08-24T10:27:21.257

And for another char we have to restructure a bit more: ~(\:y,{{>'x '=}+y,%0~2$?%}%\2&(%n* – Howard – 2013-08-24T10:39:53.183

2

J, 59 55 42 38 37 36 characters

If it's permitted to have the input at the end of the program:

(|:@|.@]^:([:|[+_7*2<[)[:[\'x'$~])~/

If not (for an extra 3 characters):

t=.(|:@|.@]^:([:|[+_7*2<[)[:[\'x'$~])~/

Usage:

   (|:@|.@]^:([:|[+_7*2<[)[:[\'x'$~])~/3 4
  x
 xx
xxx

or

   t 3 4
  x
 xx
xxx

I think this could be a fair bit shorter since most of the characters are brackets and caps to keep it in an implicit style.

Edit
Using a gerund and the agenda verb has chopped off a few characters, but there's still too many caps in there for my liking.

Edit 2
That's a bit more like it. Dumping the agenda for a list of how many rotations are required gets rid of most of the extra brackets and a few caps.

Edit 3
Got rid of the last extraneous cap and a pair of brackets in the process. Need to find a cheaper way of encoding the number of rotations required.

Edit 4 Use prefix instead of suffix to chop off a character. Enables a different way of creating the list which doesn't save any characters. Bugger.

Edit 5
Using a formula to chop off another character. Still feel this bit could be shorter.

Gareth

Posted 2013-08-23T23:45:09.973

Reputation: 11 678

1

Python 106 Characters

w,d=map(int,raw_input().split())
for e in range(1,w+1)[::d/3*2-1]:print('%'+'-+'[d%2]+str(w)+'s')%('*'*e)

Abhijit

Posted 2013-08-23T23:45:09.973

Reputation: 2 841

1

Python 3, 91

Based on Abhijit's answer.

Modified the creation of the output string to avoid the sum of strings and the ugly 1s in the range. Python 3 gets rid of the raw_ in raw_input, but makes necessary to use // for integer divison and to add parantheses for print, so that saves only one character.

w,d=map(int,input().split())
for e in range(w)[::d//3*2-1]:print('%*s'%(w-d%2*2*w,'x'*-~e))

Reinstate Monica

Posted 2013-08-23T23:45:09.973

Reputation: 929

0

Kitten, 140

def s{><replicate}
getLine{' 'neChar}span{readInt fromSome}toBoth->{w n}
w 0 if(n 2>){><}..
{<>w>< -{'X's}{' 's}both if(n 2%0=){><}cat say}each

Ungolfed:

getLine
{' ' neChar} span
{readInt fromSome} toBoth
->{ width corner }

width 0
if (corner 2 >):
  swap
..

{ ->index
  'X' index replicate
  ' ' (width index -) replicate
  if (corner 2 % 0 =):
    swap
  cat say
} each

Evidence that I need to implement overloading and flesh out the standard library.

Jon Purdy

Posted 2013-08-23T23:45:09.973

Reputation: 471