25
\$\begingroup\$

Here is a simple, bite-sized (byte-sized?) code golf: given a non-empty list of positive integers less than 10, print a block-diagonal matrix, where the list specifies the size of the blocks, in order. The blocks must consist of positive integers less than 10. So if you're given as input

[5 1 1 2 3 1]

Your output could be, for instance,

1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1

or

1 2 3 4 5 0 0 0 0 0 0 0 0
6 7 8 9 1 0 0 0 0 0 0 0 0
2 3 4 5 6 0 0 0 0 0 0 0 0
7 8 9 1 2 0 0 0 0 0 0 0 0
3 4 5 6 7 0 0 0 0 0 0 0 0
0 0 0 0 0 8 0 0 0 0 0 0 0
0 0 0 0 0 0 9 0 0 0 0 0 0
0 0 0 0 0 0 0 1 2 0 0 0 0
0 0 0 0 0 0 0 3 4 0 0 0 0
0 0 0 0 0 0 0 0 0 5 6 7 0
0 0 0 0 0 0 0 0 0 8 9 1 0
0 0 0 0 0 0 0 0 0 2 3 4 0
0 0 0 0 0 0 0 0 0 0 0 0 5

or something like that. The elements in the matrix must be separated by (single) spaces, and the rows separated by (single) newlines. There must not be leading or trailing spaces on any lines. You may or may not print a trailing newline.

You may write a function or program, taking input via STDIN (or closest alternative), command-line argument or function argument, in any convenient string or list format (as long as it isn't preprocessed). However, the result must be printed to STDOUT (or closest alternative), as opposed to returned from a function, say.

You must not use any built-in functions designed to create block-diagonal matrices.

This is code golf, so the shortest submission (in bytes) wins.

Leaderboards

I expect the array-based languages (like J and APL) to have the edge here, but I don't want that to discourage people from trying to do as well as they can in their language of choice. So here is a Stack Snippet to generate both a regular leaderboard and an overview of winners by language. So why not try and grab a spot on the latter?

To make sure that your answer shows up, please start your answer with a headline, using the following Markdown template:

# Language Name, N bytes

where N is the size of your submission. If you improve your score, you can keep old scores in the headline, by striking them through. For instance:

# Ruby, <s>104</s> <s>101</s> 96 bytes

function answersUrl(e){return"http://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function getAnswers(){$.ajax({url:answersUrl(page++),method:"get",dataType:"jsonp",crossDomain:true,success:function(e){answers.push.apply(answers,e.items);if(e.has_more)getAnswers();else process()}})}function shouldHaveHeading(e){var t=false;var n=e.body_markdown.split("\n");try{t|=/^#/.test(e.body_markdown);t|=["-","="].indexOf(n[1][0])>-1;t&=LANGUAGE_REG.test(e.body_markdown)}catch(r){}return t}function shouldHaveScore(e){var t=false;try{t|=SIZE_REG.test(e.body_markdown.split("\n")[0])}catch(n){}return t}function getAuthorName(e){return e.owner.display_name}function process(){answers=answers.filter(shouldHaveScore).filter(shouldHaveHeading);answers.sort(function(e,t){var n=+(e.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0],r=+(t.body_markdown.split("\n")[0].match(SIZE_REG)||[Infinity])[0];return n-r});var e={};var t=0,c=0,p=-1;answers.forEach(function(n){var r=n.body_markdown.split("\n")[0];var i=$("#answer-template").html();var s=r.match(NUMBER_REG)[0];var o=(r.match(SIZE_REG)||[0])[0];var u=r.match(LANGUAGE_REG)[1];var a=getAuthorName(n);t++;c=p==o?c:t;i=i.replace("{{PLACE}}",c+".").replace("{{NAME}}",a).replace("{{LANGUAGE}}",u).replace("{{SIZE}}",o).replace("{{LINK}}",n.share_link);i=$(i);p=o;$("#answers").append(i);e[u]=e[u]||{lang:u,user:a,size:o,link:n.share_link}});var n=[];for(var r in e)if(e.hasOwnProperty(r))n.push(e[r]);n.sort(function(e,t){if(e.lang>t.lang)return 1;if(e.lang<t.lang)return-1;return 0});for(var i=0;i<n.length;++i){var s=$("#language-template").html();var r=n[i];s=s.replace("{{LANGUAGE}}",r.lang).replace("{{NAME}}",r.user).replace("{{SIZE}}",r.size).replace("{{LINK}}",r.link);s=$(s);$("#languages").append(s)}}var QUESTION_ID=45550;var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe";var answers=[],page=1;getAnswers();var SIZE_REG=/\d+(?=[^\d&]*(?:&lt;(?:s&gt;[^&]*&lt;\/s&gt;|[^&]+&gt;)[^\d&]*)*$)/;var NUMBER_REG=/\d+/;var LANGUAGE_REG=/^#*\s*([^,]+)/
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src=https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js></script><link rel=stylesheet type=text/css href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"><div id=answer-list><h2>Leaderboard</h2><table class=answer-list><thead><tr><td></td><td>Author<td>Language<td>Size<tbody id=answers></table></div><div id=language-list><h2>Winners by Language</h2><table class=language-list><thead><tr><td>Language<td>User<td>Score<tbody id=languages></table></div><table style=display:none><tbody id=answer-template><tr><td>{{PLACE}}</td><td>{{NAME}}<td>{{LANGUAGE}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table><table style=display:none><tbody id=language-template><tr><td>{{LANGUAGE}}<td>{{NAME}}<td>{{SIZE}}<td><a href={{LINK}}>Link</a></table>

\$\endgroup\$

24 Answers 24

16
\$\begingroup\$

J, 7 bytes

Thanks for FUZxxl for the 2-byte improvement.

Array based languages should be counted here in a different competition as they have a huge advantage. :)

   =/~@#<\

   (=/~@#<\) 3 1 1 2
1 1 1 0 0 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 0 0
0 0 0 0 0 1 1
0 0 0 0 0 1 1

Another 7-byte approach:

#]=@##\

Explanation for the old version ([:=/~]#<\):

The first step is generating n piece of similar things (e.g. numbers) for every list element n. These should be different from the other elements'. E.g. using the natural numbers 3 1 1 2 becomes 0 0 0 1 2 3 3.

To save on bytes we use the boxed prefixes of the list:

   ]#<\ 3 1 1 2
┌─┬─┬─┬───┬─────┬───────┬───────┐
│3│3│3│3 1│3 1 1│3 1 1 2│3 1 1 2│
└─┴─┴─┴───┴─────┴───────┴───────┘

With the =/~ verb we create a table of Descartes products of these boxed prefixes and each cell will be 1 if the two entries are equal 0 otherwise.

\$\endgroup\$
  • 2
    \$\begingroup\$ I don't think the parentheses around [:=/~]#<\ count towards your score. Also, =/~@#<\ for two extra bytes shaved off. \$\endgroup\$ – FUZxxl Feb 11 '15 at 10:49
  • \$\begingroup\$ "However, the result must be printed to STDOUT (or closest alternative), as opposed to returned from a function, say." You probably need either explicit input (so it's not just a function) or explicit output. \$\endgroup\$ – marinus Feb 11 '15 at 17:48
  • \$\begingroup\$ @marinus J prints the result of an expression to stdout if it's not bound to a variable. \$\endgroup\$ – FUZxxl Feb 13 '15 at 17:20
  • \$\begingroup\$ @FUZxxl: yes, but (=/~@#<\) is just a function. You'd have to actually apply it to something to get an expression, so you'd need explicit input (".1!:1[1), or if you want to submit a function, that function should actually print the value and not just return it (like echo@ or something). \$\endgroup\$ – marinus Feb 15 '15 at 14:13
11
\$\begingroup\$

APL, 10

∘.=⍨∆/⍋∆←⎕

Example:

      ∘.=⍨∆/⍋∆←⎕
⎕:
      5 1 1 2 3 1 
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1

Explanation:

  • ∆←⎕: read input, store in .
  • ⍋∆: find permutation that sorts (this gives an unique value for each value in the input)
  • ∆/: for each of those unique values, repeat it N times, where N is the corresponding value in the input
  • ∘.=⍨: make a matrix comparing each value in that list to the other values.
\$\endgroup\$
  • \$\begingroup\$ To test this on http://tryapl.org, you might want to use the dfn {∘.=⍨⍵/⍋⍵}, as the site filters all uses of (except for ⎕IO and stuff like that). \$\endgroup\$ – FUZxxl Feb 11 '15 at 10:53
  • 1
    \$\begingroup\$ @FUZxxl: it says "However, the result must be printed to STDOUT (or closest alternative), as opposed to returned from a function, say.", so {∘.=⍨⍵/⍋⍵} isn't valid. You'd need {⎕←∘.=⍨⍵/⍋⍵}, which not only costs two characters but still wouldn't work on TryAPL. (And in general, TryAPL is too limited to be useful.) \$\endgroup\$ – marinus Feb 11 '15 at 11:10
  • \$\begingroup\$ If it has to print out the result, wouldn't you need a ⎕← anyway, even without the dfn? \$\endgroup\$ – FUZxxl Feb 11 '15 at 11:31
  • \$\begingroup\$ @FUZxxl: no, the output of an expression is printed automatically if nothing else is done with it. \$\endgroup\$ – marinus Feb 11 '15 at 11:41
  • \$\begingroup\$ Ah, I see. I was under the impression that this only happens when you are using the interpreter interactively. \$\endgroup\$ – FUZxxl Feb 11 '15 at 11:44
7
\$\begingroup\$

R, 69 63

function(x)write(+outer(i<-rep(1:length(x),x),i,"=="),1,sum(x))

Test Case:

(function(x)write(+outer(i<-rep(1:length(x),x),i,"=="),1,sum(x)))(c(5,1,1,3,1))
1 1 1 1 1 0 0 0 0 0 0 
1 1 1 1 1 0 0 0 0 0 0 
1 1 1 1 1 0 0 0 0 0 0 
1 1 1 1 1 0 0 0 0 0 0 
1 1 1 1 1 0 0 0 0 0 0 
0 0 0 0 0 1 0 0 0 0 0 
0 0 0 0 0 0 1 0 0 0 0 
0 0 0 0 0 0 0 1 1 1 0 
0 0 0 0 0 0 0 1 1 1 0 
0 0 0 0 0 0 0 1 1 1 0 
0 0 0 0 0 0 0 0 0 0 1

The outer function does most of the work here, then its just a case of getting the output looking right - Thanks to @Vlo for his help with that

\$\endgroup\$
  • \$\begingroup\$ Very nice solution \$\endgroup\$ – MickyT Feb 11 '15 at 18:03
  • \$\begingroup\$ Great solution. Never thought about using -/+ to coerce logical. Save a few bytes function(x)write(+outer(i<-rep(1:length(x),x),i,"=="),1,sum(x)) 63 \$\endgroup\$ – Vlo Feb 12 '15 at 19:24
6
\$\begingroup\$

Python 3, 103 97 82 78 76 bytes

def P(L,n=0):k,*L=L;exec("print(*[0]*n+[1]*k+[0]*sum(L));"*k);L and P(L,n+k)

Using splat to take advantage of the space-separating nature of print, with a bit of recursion.

\$\endgroup\$
6
\$\begingroup\$

Ruby, 86 90 83 bytes

My first golf ever!

->l{n=l.reduce :+;s=0;l.map{|x|x.times{puts ([0]*s+[1]*x+[0]*(n-x-s))*" "};s+=x}}

Receives an array with the integers, prints the expected result:

$ (->l{n=l.reduce :+;s=0;l.map{|x|x.times{puts ([0]*s+[1]*x+[0]*(n-x-s))*" "};s+=x}}).call([5, 1, 1, 2, 3, 1])
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1

Edit:

Thanks to Martin Büttner for helping me shortening some things!

\$\endgroup\$
  • 1
    \$\begingroup\$ You can save some more characters: ->(l) can be ->l. map is shorter than each. .join(" ") can be shortened to *" ". \$\endgroup\$ – Martin Ender Feb 11 '15 at 13:04
6
\$\begingroup\$

Matlab, 60 54 bytes

This would be Matlab's special field IF we could use builtin functions...

Thanks @sanchises for fixing the error I missed.

c=0;a=input('');for A=a;v=c+1:c+A;d(v,v)=1;c=c+A;end;d
\$\endgroup\$
  • \$\begingroup\$ Wooow, it was until now that I noticed that this js snippet actually produces a leaderboard!!! How did I never notice this??? Thanks for pointing this out=) \$\endgroup\$ – flawr Feb 10 '15 at 22:19
  • \$\begingroup\$ I know, right? It's really cool! \$\endgroup\$ – Alex A. Feb 10 '15 at 22:25
  • 1
    \$\begingroup\$ I was about to post almost the same answer :-) \$\endgroup\$ – Luis Mendo Feb 10 '15 at 22:55
  • \$\begingroup\$ The exact same or something slightly different? =) (Well apart from variable names.) \$\endgroup\$ – flawr Feb 10 '15 at 23:08
  • \$\begingroup\$ Too similar for me to post it :-) \$\endgroup\$ – Luis Mendo Feb 11 '15 at 22:52
4
\$\begingroup\$

CJam, 21

q~{T):Ta*~}%_f{f=S*N}

Try it at http://cjam.aditsu.net/

Explanation:

q~          read and evaluate the input array
{…}%        transform each number using the block
    T):T    increment T (initially 0)
    a*      wrap T in an array and repeat it <number> times
    ~       dump the repeated numbers so they end up in a flat array
_           duplicate the array
f{…}        for each array item and the array
    f=      compare the current item with each item, resulting in an array of 1 and 0
    S*      join with spaces
    N       add a newline
\$\endgroup\$
4
\$\begingroup\$

Python 3, 79

def f(l,s=0):
 for x in l:r=[0]*sum(l);r[s:s+x]=[1]*x;s+=x;exec("print(*r);"*x)

Tracks the leftmost index of the block as s and makes the x entries after it be 1, where x is the current block size. This row is then printed x times. Python 3 is needed to do print(*r).

\$\endgroup\$
  • \$\begingroup\$ It's one char shorter to just do express r as [0]*s+[1]*x+[0]*(sum(l)-s-x), but I'm still looking for a better way. \$\endgroup\$ – xnor Feb 11 '15 at 0:20
4
\$\begingroup\$

Matlab, 53 bytes

Though it is only one char shorter than the other Matlab fragment, I figured the code is sufficiently different to warrant a new answer:

d=[];a=input('');for A=a;v=1:A;d(end+v,end+v)=1;end;d

The main trick is of course out of bounds indexing, but this is combined with using end as a variable to make it more compact.

\$\endgroup\$
  • 1
    \$\begingroup\$ Damn - I spent half an hour trying to golf end+1:end+v to get rid of a 'counter' variable, and I didn't think of this solution. \$\endgroup\$ – Sanchises Feb 12 '15 at 16:14
  • \$\begingroup\$ Indeed, as @Geobits mentioned the attempted edit by an anonymous into blkdiag would violate the requirements. Just for reference I will put the core of it here anyway: blkdiag(A,ones(i)) \$\endgroup\$ – Dennis Jaheruddin Feb 13 '15 at 11:29
4
\$\begingroup\$

Haskell, 118 116 bytes

(#)=replicate
f i=putStr$[e#(unwords$sum h#"0"++e#"1"++sum t#"0")|(h,e:t)<-map(`splitAt`i)[0..length i-1]]>>=unlines

Usage: f [2,1,1,3]

Output:

1 1 0 0 0 0 0
1 1 0 0 0 0 0
0 0 1 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 1 1 1
0 0 0 0 1 1 1
0 0 0 0 1 1 1

How it works:

[0..length i-1]           for each index n of the input list i
(h,e:t)<-map(`splitAt`i)  split i at n and
                            let e be the element at index n
                            let h be the list of elements to the left of e
                            let t be the list of elements to the right of e
                          foreach triple h, e, t make a list of
sum h # "0" ++              sh copies of "0" (sh = the sum of the elements of h) followed by
e # "1" ++                  e copies of "1" followed by
sum t # "0"                 st copies of "0" (st = the sum of the elements of t)
unwords                   join those list elements with spaces inbetween
e #                       make e copies
>>=unlines                join those lists with newlines inbetween
putStr                    print
\$\endgroup\$
  • \$\begingroup\$ You can save two bytes by doing (h,e:t)<-map(`splitAt`i)[0..length i-1], since n is not used outside the let binding. \$\endgroup\$ – Zgarb Feb 15 '15 at 15:38
  • \$\begingroup\$ @Zgarb: nice find. Thanks! \$\endgroup\$ – nimi Feb 15 '15 at 22:37
3
\$\begingroup\$

Pyth, 23 21 bytes

GitHub repository for Pyth

Ju+G*]GHQYFNJjdmsqdNJ

Input is a list of integers, like [3, 1, 1, 2]. Try it online: Pyth Compiler/Executor

Uses a quite similar idea as randomra's J code. The first part of the code Ju+G*]GHQY generates n parts of similar things. For the example input [3, 1, 1, 2] the result looks like this:

[
 [], 
 [], 
 [], 
 [[], [], []], 
 [[], [], [], [[], [], []]], 
 [[], [], [], [[], [], []], [[], [], [], [[], [], []]]], 
 [[], [], [], [[], [], []], [[], [], [], [[], [], []]]]
]

First three identical elements, than one element , then one element again and at the end two identical elements.

Ju+G*]GHQY
 u      QY  reduce the input Q, start with empty list G=[]
            for each H in input, replace the value of G by:
  +G*]GH       G+[G]*H
J           store the result in J

The second part of the code is comparing the elements of the Cartesian product and printing it.

FNJjdmsqdNJ
FNJ          for N in J:
     m    J     map each element d of J to
       qdN          the boolean value of d == N
      s             and convert it to an integer (0 = False, 1 = True)
   jd           print the resulting list seperated by d (=space)
\$\endgroup\$
3
\$\begingroup\$

C++ , 294 bytes

Compiler used - GCC 4.9.2

#include<bits/stdc++.h>
using namespace std;
#define F(a,b) for(a=0;a<b;a++)
#define V vector<int>
int n,i,j,s,o;
main(){V v;while(cin>>n)v.push_back(n),s+=n;vector<V> m(s,V(s,0));F(i,v.size()){F(j,v[i])F(n,v[i])m[j+o][n+o]=1;o+=v[i];}F(j,s){F(n,s)cout<<m[j][n]<<((n==s-1)?"":" ");cout<<"\n";}}

Explanation -:

#include<bits/stdc++.h>
using namespace std;
#define F(a,b) for(a=0;a<b;a++)
#define V vector<int>
int n, i, j, s, o;
/*
 n = Used to take inputs, and as an iterator after that
 i, j = Iterators
 s = sum of all the inputs
 o = offset ( used to find the location of the starting cell of the next matrix of 1's )
*/

main()
{
    V v;
    while ( cin >> n )  // Take input
    {
        v.push_back( n ), s += n;
    }

    vector<V> m( s, V( s, 0 ) ); // m is a matrix of size (s*s) with all elements initialized to 0
    F( i, v.size() )
    {
        F( j, v[i] )F( n, v[i] )m[j + o][n + o] = 1; // Assign 1 to the required cells
        o += v[i]; // Add the value of the current element to the offset
    }

    F( j, s )  // Output the matrix
    {
        F( n, s )cout << m[j][n] << ( ( n == s - 1 ) ? "" : " " ); // Prevent any trailing whitespace
        cout << "\n";
    }
}
\$\endgroup\$
2
\$\begingroup\$

Java, 163

a->{int n=a.stream().mapToInt(x->x).sum(),t=0,j,k;for(int i:a){for(j=0;j++<i;System.out.println("\b"))for(k=0;k<n;)System.out.print(k>=t&k++<t+i?"1 ":"0 ");t+=i;}}

A consumer which accepts a list of integers.

Readable version, with boilerplate code:

java.util.function.Consumer<java.util.List<Integer>> c = a -> {
    int n = a.stream().mapToInt(x -> x).sum(), t = 0, j, k;
    for (int i : a) {
        for (j = 0; j++ < i; System.out.println("\b")) {
            for (k = 0; k < n;) {
                System.out.print(k >= t & k++ < t + i ? "1 " : "0 ");
            }
        }
        t += i;
    }
};

Invoke using:

List list = Arrays.asList(5, 1, 1, 2, 3, 1);
c.accept(list);
\$\endgroup\$
2
\$\begingroup\$

Python 2, 163 114 bytes

gnibbler golfed this a bunch.

h=input()
r=range
l=len(h)
for i in r(l):
 for k in r(h[i]):print" ".join("01"[i==j]for j in r(l)for x in r(h[j]))
\$\endgroup\$
  • 3
    \$\begingroup\$ how about print" ".join("01"[i==j]for j in r(l(h))for x in r(h[j]))? \$\endgroup\$ – gnibbler Feb 10 '15 at 20:06
  • \$\begingroup\$ Aha! I thought I could do something like that. \$\endgroup\$ – KSFT Feb 10 '15 at 23:47
  • \$\begingroup\$ This seems to only print one row of each block. \$\endgroup\$ – xnor Feb 11 '15 at 0:14
  • \$\begingroup\$ @xnor You're right; I fixed it. \$\endgroup\$ – KSFT Feb 11 '15 at 0:18
2
\$\begingroup\$

Python 3, 74

def f(a,p=0):n=a.pop(0);exec("print(*'0'*p+'1'*n+'0'*sum(a));"*n);f(a,p+n)
\$\endgroup\$
  • \$\begingroup\$ Doesn't this terminate with an error? \$\endgroup\$ – xnor Feb 11 '15 at 4:25
  • \$\begingroup\$ @xnor yes it does! \$\endgroup\$ – feersum Feb 11 '15 at 4:26
  • 1
    \$\begingroup\$ @feersum Is that allowed? I don't see any meta post on the issue. What do you think, Martin? If it's allowed, Sp3000 can save 6 chars by getting rid of the and short-circuit. \$\endgroup\$ – xnor Feb 11 '15 at 5:40
  • \$\begingroup\$ @xnor Does the error terminate the program or only the function call? If this terminates the program, then no I don't think it's allowed. I've expressed my opinion on this here on meta. I also think if feersum was of the opinion that this is completely legit, he would have stated it in his answer instead of hoping that no one notices. \$\endgroup\$ – Martin Ender Feb 11 '15 at 12:09
  • \$\begingroup\$ @MartinBüttner Terminate the program, if I understand what you're asking. If you were to do f([1,2,3]);print("Done"), the error would end the program after it prints the block matrix, and it wouldn't get to printing "Done". \$\endgroup\$ – xnor Feb 11 '15 at 21:10
2
\$\begingroup\$

JavaScript (ES6), 103 107

103 bytes as an anonymous function, not counting F= (but you need this to test it)

F=l=>alert(l.map((n,y)=>(l.map((n,x)=>Array(n).fill(x==y|0))+'\n').repeat(n))
.join('').replace(/,/g,' '))

Test In Firefox/FireBug console

F([5,1,1,2,3,1])

Output

1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1
\$\endgroup\$
1
\$\begingroup\$

Pyth, 31 30

FbQVbjd++*]0Z*b]b*]0--sQbZ)~Zb

A pretty naive program, takes the input on stdin. This can probably be golfed more ;)

Thanks @Jakube for pointing out a wasted char

Try it here

\$\endgroup\$
1
\$\begingroup\$

Perl, 69

#!perl -na
$j=s/./0 x$&/ger;print+($j|$i.1x$_)=~s/\B/ /gr x($i.=0 x$_,$_)for@F

Uses standard input:

$ perl a.pl <<<"1 2 3"
1 0 0 0 0 0
0 1 1 0 0 0
0 1 1 0 0 0
0 0 0 1 1 1
0 0 0 1 1 1
0 0 0 1 1 1
\$\endgroup\$
  • \$\begingroup\$ strangely, this doesn't print newlines for me on ideone. also, according to this post you should code the custom shebang as 4 bytes, not two. you can fix that by not using the shebag but instead using the flags on the interpreter and calling the code with -e instead of from a file (see examples in that meta post). also, I think you don't need the n flag - according to the perldoc, a sets n implicitly. \$\endgroup\$ – Martin Ender Feb 11 '15 at 11:53
  • \$\begingroup\$ The program reuses the eol from the standard input. Your ideone setup works when you add it. As for the character count, I count it this way in all my answers, and I've seen others do it this way too. I have seen the post you linked before, but I don't get what it means by "count the difference to perl -nl file.pl". Original perlgolf rules would count the hyphen but not the space so 3 characters in this case. \$\endgroup\$ – nutki Feb 11 '15 at 14:03
  • \$\begingroup\$ @MartinBüttner, it is all moot anyway as randomra's approach gives much shorter solution: -lna //,print join$",map$'==$_|0,@,for@,=map{(++$i)x$_}@F. BTW my version of Perl does not set -n with -a, it must be a recent addition. \$\endgroup\$ – nutki Feb 11 '15 at 14:39
1
\$\begingroup\$

R, 117 144 137 133 129 123 bytes

Reasonably verbose at the moment. Should be able to shave a few more out. Gained a number of bytes formatting it correctly, but saved some swapping out the matrix for an array.

Thanks to Alex for the tip on the replacing sep with s and removing the function name.

Dropped the array completely and used a series of reps to build each line.

Although soundly beaten by Miff, his solution made me realise I could drop the s=' ' altogether.

function(i){s=sum(i);i=cumsum(i);b=0;for(n in 1:s){d=i[i>=n][1];cat(c(rep(0,b),rep(1,d-b),rep(0,s-d)),fill=T);if(d==n)b=d}}

And the test

> (function(i){s=sum(i);i=cumsum(i);b=0;for(n in 1:s){d=i[i>=n][1];cat(c(rep(0,b),rep(1,d-b),rep(0,s-d)),fill=T,s=' ');if(d==n)b=d}})(c(5,1,1,3,1))
1 1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 1
> 
\$\endgroup\$
  • \$\begingroup\$ You can save 2 bytes using partial matching of function parameters. In cat(), change sep= to s= since no other recognized parameters for that function begin with "s". \$\endgroup\$ – Alex A. Feb 10 '15 at 21:19
  • \$\begingroup\$ @Alex Thanks, didn't realise that. Still on a learning curve \$\endgroup\$ – MickyT Feb 10 '15 at 21:51
  • \$\begingroup\$ You can save another 2 by removing f=. This gives you a function object. If you do that, you just have to stipulate that it be assigned using something like f= before running it. I didn't realize that was legit in contests like this until I saw Martin Büttner do it with Ruby. \$\endgroup\$ – Alex A. Feb 10 '15 at 21:57
1
\$\begingroup\$

Batch - 226 Bytes

@echo off&setLocal enableDelayedExpansion&set c=0&for %%a in (%*)do set/ac+=1&for /l %%b in (1,1,%%a)do (set l=&set d=0&for %%c in (%*)do (set/ad+=1&for /l %%d in (1,1,%%c)do if !d!==!c! (set l=!l!1)else set l=!l!0)
echo !l!)

Takes input from stdin (C:\>script.bat 5 1 1 2 3 1) and echo's output. Unfortunately I couldn't get that last echo on the same line, otherwise I could probably call the whole line within cmd/von/c to avoid having to enable delayed expansion the long way.

Nice and neat - nothing but grunt work:

@echo off
setLocal enableDelayedExpansion
set c=0
for %%a in (%*) do (
    set /a c+=1
    for /l %%b in (1,1,%%a) do (
        set l=
        set d=0
        for %%c in (%*) do (
            set /a d+=1
            for /l %%d in (1,1,%%c) do if !d!==!c! (set l=!l!1) else set l=!l!0
        )
        echo !l!
    )
)
\$\endgroup\$
1
\$\begingroup\$

Haskell, 124

(%)=replicate
d l=fst$foldr(\x(m,n)->(m>>mapM_(\_->putStrLn$unwords$n%"0"++x%"1"++(sum l-n-x)%"0")[1..x],n+x))(return(),0)l

Produces output by combining IO actions through mapM_ and foldr. The function d should be given a list of ints.

\$\endgroup\$
1
\$\begingroup\$

K, 30 bytes

{"i"$,/x#',:',/'g=\:\:x#'g:<x}

Basically stole marinus's answer

k){"i"$,/x#',:',/' g=\:\:x#'g:<x}5 1 1 2 3 1
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 1 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 1
\$\endgroup\$
1
\$\begingroup\$

Octave, 49 41 bytes

@(a)(c=repelems(b=1:length(a),[b;a]))'==c
\$\endgroup\$
0
\$\begingroup\$

STATA, 155 bytes

di _r(a)
forv x=1/wordcount($a){
gl b=word($a,`x')
gl c=_N+1
set ob _N+$b
forv y=$c/_N{
g d`y'=_n>=$c
}
}
forv z=1/_N{
replace d`z'=0 if d`z'>1
}
l,noo noh
\$\endgroup\$
  • \$\begingroup\$ Can I test this online somewhere? \$\endgroup\$ – Martin Ender Feb 10 '15 at 19:39
  • \$\begingroup\$ @MartinBüttner: As far as I know, there are no online compilers for Stata since it's proprietary. Same goes for languages like SAS. \$\endgroup\$ – Alex A. Feb 10 '15 at 21:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.