7
\$\begingroup\$

Background:

Here's a little simple challenge. You want to be able to find out whether the arrays inside an array have the same length.

Input:

Your input should consist of exactly one array (this is the value passed to the function, not a user input). Your function takes exactly 1 parameter. It could contain arrays or be empty. No error checking needed, assume only list is ever passed in. Assume a 1-D array such as [1] or [1,2,3,4,5] is never passed in.

Output:

Return true if all the list elements have the same length, false if they don't, and the parameter itself if the list is empty (or null if your language doesn't support multiple return types).

Some test cases:

List: [] - [] (or null/your language equivalent)
List: [[1], [1], [2]] - True
List: [[1]] - True
List: [[1, 2, 3, 4]] - True
List: [[1, 2, 3, 4, 5], [2], [12, 314123]] - False
List: [[1, 2, 3, 4], [1]] - False

No std(in/out) input/output needed (however, it is allowed, just not required!), the function only needs to return boolean values true or false; or the parameter itself if the function is passed an empty list (or null/your language equivalent). Only one return value is returned.

Rules:

Shortest byte count wins, only function is necessary (full programs are allowed if you desire).

\$\endgroup\$
  • 1
    \$\begingroup\$ what if we can't return different types (Arrays / Booleans)? \$\endgroup\$ – nimi Jun 9 '16 at 21:51
  • 1
    \$\begingroup\$ As the parameter is only returned when it is empty, how about some kind of option type like Haskell's Maybe, i.e. Nothing for the empty list and Just True/Just False else? Or Either -> Left [] / Right True. Basically any wrapper that can combine two types. \$\endgroup\$ – nimi Jun 9 '16 at 22:14
  • 1
    \$\begingroup\$ Are the sublist elements always going to be positive integers? \$\endgroup\$ – Neil Jun 9 '16 at 23:26
  • 8
    \$\begingroup\$ The special-case output for the empty list, especially one of a different type, is an extraneous task that makes solutions needlessly uglier. \$\endgroup\$ – xnor Jun 10 '16 at 3:11
  • 1
    \$\begingroup\$ Welcome to PPCG! Usually we first post a question in the Sandbox for Proposed Challenges. That way we can first get feedback and discussions to make the question close to perfect before posting it here. It's advisable to keep it in the Sandbox for ±72 hours so enough people can give recommendations, remarks and ask questions regarding your challenge. More info can be found in the Sandbox itself. (That being said, it looks like a good question, but in the Sandbox people often ask about edge/cases.) \$\endgroup\$ – Kevin Cruijssen Jun 10 '16 at 7:31

25 Answers 25

6
\$\begingroup\$

Pyth - 7 5 bytes

Saved 2 bytes thanks to @FryAmTheEggman.

And I was the one who told @issacg to remove the q default...

?QqCC

Test Suite.

\$\endgroup\$
  • \$\begingroup\$ I think ?QqCC works. \$\endgroup\$ – FryAmTheEggman Jun 9 '16 at 21:19
  • \$\begingroup\$ @FryAmTheEggman nice! \$\endgroup\$ – Maltysen Jun 9 '16 at 21:20
9
\$\begingroup\$

Python 2, 31

lambda l:l and l==zip(*zip(*l))

This requires the lists to be lists of tuples. zip Drops extra elements if the input was ragged, so double zipping is only a noop if the lists all have the same length.

Try it here

\$\endgroup\$
4
\$\begingroup\$

Jelly, 5 bytes

L€E⁸ȧ

Try it online!

How it works

L€E⁸ȧ  Monadic link. Argument: A (list)

L€     Map length over the list.
  E    Test if all elements are equal.
   ⁸ȧ  Take the logical AND of A and the resulting Boolean.
\$\endgroup\$
4
\$\begingroup\$

Perl 6, 17 bytes

{$_??[==] $_!!$_}

[==] $_ does a reduce of the input ($_) with &infix:<==>. &infix:<==> is a Numeric operator so it coerces its inputs to Numeric. The rest is just the ternary operator ?? !!.

This is roughly equivalent to

sub ( $_ ) {
  if $_ {
    # the 「map」 is for clarity, it is not needed
    $_.map(*.elems).reduce(&infix:<==>)
    # 「[OP] List」 is actually smarter than 「List.reduce(&infix:«OP»)」
    # as it takes into account operator chaining, and associativity
  } else {
    $_
  }
}

Test:

#! /usr/bin/env perl6

use v6.c;
use Test;

# put it into the lexical namespace for clarity
my &same-elems = {$_??[==] $_!!$_}

my @tests = (
  [] => [],
  [[1], [1], [2]] => True,
  [[1],] => True,
  [[1, 2, 3, 4],] => True,
  [[1, 2, 3, 4, 5], [2], [12, 314123]] => False,
  [[1, 2, 3, 4], [1]] => False,
);

plan +@tests;

for @tests -> ( :key(@input), :value($expected) ) {
  is same-elems(@input), $expected, @input.perl
}
1..6
ok 1 - []
ok 2 - [[1], [1], [2]]
ok 3 - [[1],]
ok 4 - [[1, 2, 3, 4],]
ok 5 - [[1, 2, 3, 4, 5], [2], [12, 314123]]
ok 6 - [[1, 2, 3, 4], [1]]
\$\endgroup\$
4
\$\begingroup\$

Javascript ES6, 44 43 42 bytes

Saved 1 byte thanks to @Neil

a=>a[0]?!a.some(b=>b.length-a[0].length):a

Alternative solutions

a=>a[0]?a.every(b=>b.length==a[0].length):a // 43
a=>a[0]?new Set(a.map(b=>b.length)).size==1:a // 45
a=>a[0]?Math.max(...a.map(b=>b.length))==a[0].length:a // 54
a=>a[0]?[a[0].length,...a].reduce((b,d)=>b==d.length):a // 55, doesn't work as intended

Somehow the stacksnippet doesn't print [], try it in your console for the actual result.

f=
a=>a[0]?a.every(b=>b.length==a[0].length):a

z.innerHTML = [
  [],
  [[1], [1], [2]],
  [[1]],
  [[1, 2, 3, 4]],
  [[1, 2, 3, 4, 5], [2], [12, 314123]],
  [[1, 2, 3, 4], [1]]
].map(m=>JSON.stringify(f(m))).join`<br>`
<pre id=z>

(yay for crossed out 44)

\$\endgroup\$
  • \$\begingroup\$ Your second alternative won't work, reduce uses the result of the previous function call as the first parameter to the next. Even if it did work, c costs you a byte. c costs you 4 bytes in your third alternative, since it's an unused variable. \$\endgroup\$ – Neil Jun 9 '16 at 23:32
  • \$\begingroup\$ I think I shaved off a byte: a=>a[0]?!a.some(b=>b.length-a[0].length):a \$\endgroup\$ – Neil Jun 9 '16 at 23:33
  • 1
    \$\begingroup\$ "Somehow" == in JavaScript [].toString() returns an empty string. \$\endgroup\$ – traktor53 Jun 10 '16 at 0:18
  • \$\begingroup\$ Array.prototype.toString() is equivalent to Array.prototype.join() with no arguments, that's why. \$\endgroup\$ – Patrick Roberts Jun 10 '16 at 3:57
  • \$\begingroup\$ Try wrapping the array in JSON.stringify to display it correctly. \$\endgroup\$ – Conor O'Brien Jun 10 '16 at 15:43
3
\$\begingroup\$

Swift 3 - 47 Bytes

{$0.isEmpty ?nil:Set($0.map{$0.count}).count<2}

To invoke, first assign it to a variable:

 let f: ([[Any]]) -> Bool? = {$0.isEmpty ?nil:Set($0.map{$0.count}).count<2}
 f([[1], [1,2], [1,2,3]])
\$\endgroup\$
  • \$\begingroup\$ Is the initial space required? \$\endgroup\$ – Conor O'Brien Jun 10 '16 at 0:40
  • \$\begingroup\$ Nope, that was just a typo. It wasn't in my letter count anyway \$\endgroup\$ – Alexander Jun 10 '16 at 14:52
2
\$\begingroup\$

Mathematica, 22 bytes

a@{}={};a@b_:=ArrayQ@b

The requirement of a[{}] == {} ruins everything and prevents a 6 byte solution of the built-in ArrayQ, since in Mathematica a zero length array is also an array.

\$\endgroup\$
  • \$\begingroup\$ I don't have my mathematica rpi running atm, but IIRC, you can save by special casing {} by doing a@b_:=b&&ArrayQ@b \$\endgroup\$ – Maltysen Jun 9 '16 at 22:12
  • \$\begingroup\$ @Maltysen That doesn't seem to work, it'll always return the array if it is an array then (b&&c will always return b if c evaluates to True). \$\endgroup\$ – LLlAMnYP Jun 9 '16 at 22:17
  • \$\begingroup\$ why does it do that? shouldn't it return c if b is true? \$\endgroup\$ – Maltysen Jun 9 '16 at 22:18
  • \$\begingroup\$ @Maltysen Your statement is the inverse of mine and is also true. I'm referring to a@{} -> {} && ArrayQ@{} -> {} && True -> {}. This is desirable. But let b = {{1},{2},{3}}, then a@b -> b && ArrayQ@b -> b && True -> b -> {{1},{2},{3}} whereas we need True here. \$\endgroup\$ – LLlAMnYP Jun 9 '16 at 22:21
  • \$\begingroup\$ oic, can you do instead then {}&&stuff? \$\endgroup\$ – Maltysen Jun 9 '16 at 22:24
2
\$\begingroup\$

Julia, 33 bytes

!x=[]==x?x:diff(map(endof,x))⊆0

Try it online!

How it works

We redefine the unary operator ! for this task.

If x is the empty array, we simply return x.

Else, we map endof (equivalent to length) over the arrays in x and compute the differences of consecutive lengths with diff. If all length are equal, this will generate an array of 0's. Otherwise, there will be non-zero numbers in the result.

Finally, ⊆0 tests if all differences are 0 and return the corresponding Boolean.

\$\endgroup\$
2
\$\begingroup\$

Brachylog, 9 bytes

.v|:ladl1

Returns true or false or the empty list.

Explanation

.v      Unify the output with the input if it's the empty list
|       Or
:la     Apply length to each element of the input
   d    Remove all duplicates
    l1  The length of the resulting list is 1
\$\endgroup\$
2
\$\begingroup\$

Ruby, 27 bytes

->i{!i.map(&:size).uniq[1]}

Test:

s = ->i{!i.map(&:size).uniq[1]}
s[[[1, 2, 3, 4], [1]]]
=> false
s[[[1, 2, 3, 4]]]
=> true
\$\endgroup\$
2
\$\begingroup\$

PowerShell v2+, 53 bytes

param($a)if($a){($a|%{$_.count}|select -u).count-eq1}

This presumes that standard I/O methods and both programs and functions are allowed. Additionally, in PowerShell, the concept of "returning" an empty array is meaningless -- it's converted to $null as soon as it leaves scope -- and so it is the equivalent of returning nothing, which is what is done here.

We take input $a, and if it's non-empty we collect all the .counts of each sub-array. We pipe that to Select-Object with the -unique flag, take that .count and verify that it's -equal to 1. Returns Boolean $true or $false. If the input is the empty array, returns nothing (i.e., $null).

Examples

PS C:\Tools\Scripts\golfing> .\same-length-sub-arrays.ps1 ((1),(2),(3))
True

PS C:\Tools\Scripts\golfing> .\same-length-sub-arrays.ps1 ((1),(2),(3,4))
False

PS C:\Tools\Scripts\golfing> .\same-length-sub-arrays.ps1 @()

PS C:\Tools\Scripts\golfing> (.\same-length-sub-arrays.ps1 @()).GetType()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ (.\same-length-sub-arrays.ps1 @()).GetType()
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

PS C:\Tools\Scripts\golfing> (.\same-length-sub-arrays.ps1 @())-eq$null
True
\$\endgroup\$
2
\$\begingroup\$

Haskell, 48 46 bytes

f[]=Nothing
f x|h:t<-length<$>x=Just$all(==h)t

Wraps the result in the Maybe type and returns Nothing if the input is the empty list and Just True/Just False otherwise.

Usage example:

*Main> map f [[],[[1],[2],[3]],[[1]],[[1,2,3,4]],[[1,2,3,4,5],[2],[12,314123]],[[1,2,3,4],[1]]]
[Nothing,Just True,Just True,Just True,Just False,Just False]

How it works:

f[]=Nothing                   -- empty input
f x                           -- otherwise
   |(h:t)<-length<$>x         -- map length function over the input and bind h
                              -- to the first element and t to rest of the list
          =     all(==h)t     -- return whether all values in t equal h
           Just$              -- wrapped in the Maybe type 

Edit: @Lynn saved two bytes. Thanks!

\$\endgroup\$
  • \$\begingroup\$ Looks like can drop the parens around h:t. \$\endgroup\$ – Lynn Jun 23 '16 at 19:37
  • \$\begingroup\$ @Lynn: Wow. I don't think I've ever tried to drop parens in a pattern match. \$\endgroup\$ – nimi Jun 23 '16 at 21:03
2
\$\begingroup\$

Java 10, 145 129 107 106 103 93 77 bytes

Loads of bytes saved thanks to @Frozn, and by using Object as return-type, we can comply with OP's rules of returning the input-array when the array is empty, despite Java's one-return-type-only nature regarding methods.

m->{int f=1;for(var a:m)f=m[0].length!=a.length?0:f;return m.length<1?m:f>0;}

Try it online.

Explanation:

m->{                  // Method with integer-matrix parameter and Object return-type
  int f=1;            //  Flag-integer, starting at 1
  for(var a:m)        //  Loop over the rows of the matrix
    f=m[0].length!=a.length?
                      //   If the length of the first and current row aren't the same:
       0              //    Change `f` to 0
      :               //   Else:
       f;             //    Leave `f` the same
  return m.length<1?  //  If there is only one row:
          m           //   Return the input-matrix as result
         :            //  Else:
          f>0;}       //   Return whether the flag `f` is still 1 as boolean
\$\endgroup\$
  • 1
    \$\begingroup\$ I don't understand why the p = a[x].length is necessary as it seems to don't change the value of p \$\endgroup\$ – Frozn Jun 10 '16 at 9:15
  • \$\begingroup\$ @Frozn Ah, you're completely right, I screwed up!.. I've removed it. Thanks. \$\endgroup\$ – Kevin Cruijssen Jun 10 '16 at 9:28
  • 1
    \$\begingroup\$ Alright, I think you can get rid of some characters by changing the for-loop to a for each. Didn't tested it just wrote it on a piece of paper and it looked a bit shorter. Oh and in addition you can remove l so it will get even shorter. \$\endgroup\$ – Frozn Jun 10 '16 at 9:43
  • 1
    \$\begingroup\$ It's me again, I claim you can change the return type to Object to save an additional character. Also with the forearm loop you can remove the first if statement and move it to the end of the function as a ternary like return a.length < 0 ? null : 1 > 0 \$\endgroup\$ – Frozn Jun 10 '16 at 16:00
  • 1
    \$\begingroup\$ As the OP allows to return the parameter itself you can replace the return of null with a. This will save some more characters, so you could come down to 93. \$\endgroup\$ – Frozn Jun 10 '16 at 19:02
1
\$\begingroup\$

Python, 45 bytes

lambda x:x and min(x,key=len)==max(x,key=len)
\$\endgroup\$
  • 2
    \$\begingroup\$ 5 bytes shorter: f=lambda x:x and len(set(map(len,x)))<2 \$\endgroup\$ – Maltysen Jun 9 '16 at 21:36
  • \$\begingroup\$ also, yours doesn't work on [] \$\endgroup\$ – Maltysen Jun 9 '16 at 21:37
  • \$\begingroup\$ You should return the array if it's empty. \$\endgroup\$ – ospahiu Jun 9 '16 at 21:37
  • \$\begingroup\$ @Maltysen Thanks for the tip. Feel free to post that as an answer, since it's a totally different approach and I didn't come up with it. \$\endgroup\$ – DJMcMayhem Jun 9 '16 at 21:40
1
\$\begingroup\$

Octave, 51 bytes

@(x)repmat(2>n(unique(cellfun(n=@numel,x))),n(x)>0)

Online Demo

Explanation

Loops through the input (a cell array) and determines the number of elements in each entry numel, then from this array of the number of elements, we ensure that there is only one unique value: 2 > numel(unique(numberOfElements)). This will give us the boolean we want. Unfortunately, it is difficult to yield an empty array efficiently so in order to deal with the case of an empty input, we use repmat to repeat this boolean value N times where N is the number of subarrays in the input. If the input is empty this repeats the boolean value 0 times leading to [].

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

Actually, 18 bytes

`♂l╔l;Y"[].⌂"£n=1`

Try it online! (calls the function with ƒ)

Explanation:

`♂l╔l;Y"[].⌂"£n=1`  push a function:
 ♂l                   map length over input
   ╔l                 uniquify
     ;Y               1 if list is empty else 0
       "[].⌂"£n       call this function that many times:
        [].             print an empty list
           ⌂            exit
               =1     1 if length of unique list equals 1 else 0

If the function-only requirement is lifted, the equivalent program works for 15 bytes:

♂l╔l;Y`[].⌂`n=1

Try it online!

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

05Ab1E, 12 bytes

Dg0Qië€gÙg1Q

Explained

Dg0Qi          # if empty list, return input
     ë         # else
      €g       # map length over list
        Ùg1Q   # check if length of uniquified list is 1

Try it online

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

F#, 78 bytes

function
|[]->None
|x->Seq.forall(fun y->Seq.length y=Seq.length x.[0])x|>Some

Output is the F# Option type. If the input is empty output is None, else it's Some bool, where the bool value indicates whether all the sub-arrays are of equal length.

// F# Interactive
let f = 
    function
    |[]->None
    |x->Seq.forall(fun y->Seq.length y=Seq.length x.[0])x|>Some;;

val f : _arg1:#seq<'b> list -> bool option

> f [[0;1];[2];[3]];;
val it : bool option = Some false
> f [[0;1];[2;3];];;
val it : bool option = Some true
> f [];;
val it : bool option = None
\$\endgroup\$
1
\$\begingroup\$

J, 26 bytes

]`(1=[:#@~.#@>@>)@.(*@#@>)

Since J doesn't support ragged arrays, I will use boxed arrays instead. It returns 1 for true, 0 for false, and the input if empty.

Usage

   f =: ]`(1=[:#@~.#@>@>)@.(*@#@>)

   NB. Boxed array representing [[1, 2, 3, 4, 5], [2], [12, 314123]]
   < 1 2 3 4 ; 2 ; 12 314123
┌─────────────────────┐
│┌───────┬─┬─────────┐│
││1 2 3 4│2│12 314123││
│└───────┴─┴─────────┘│
└─────────────────────┘
   f < 1 2 3 4 ; 2 ; 12 314123
0
   NB. The empty list
   a:
┌┐
││
└┘
   f a:
┌┐
││
└┘
   f < 1 ; 1 ; 2
1
   f < < 1
1
   f < < 1 2 3 4
1
   f < 1 2 3 4 ; 1
0
\$\endgroup\$
1
\$\begingroup\$

Retina, 35 bytes

If only [] could return true or false. Returning a 3rd value makes it so much longer.

\[]
xx
\d|],

M`^\[(\[,*)\1*]]|x
2

Try it online

This is the core program. It removes digits and occurrences of ],, then matches if the number of commas is the same after each [. It would return 0 for []. The code above varies because I added a check for an empty list to make it match twice, then I replace 2 with nothing for a null return.

\d|],

^\[(\[,*)\1*]]
\$\endgroup\$
1
\$\begingroup\$

APL, 13 bytes

1=(×∘⍴⍴≢)∪≢¨⎕

In English:

  • compute the unique of the tallies of each of the subarrays;
  • reshape the result with the signum of its shape: if its an empty vector, it remains an empty vector;
  • is it equal to 1?
\$\endgroup\$
  • \$\begingroup\$ There's a bug: if the input is the empty list, you should return the empty list instead of 0 or 1. This returns 0. \$\endgroup\$ – marinus Jun 23 '16 at 16:49
  • \$\begingroup\$ @marinus, you are absolutely right: I didn't read carefully enough the specs. Let's see if it's worth trying to fix it... \$\endgroup\$ – lstefano Jun 23 '16 at 17:30
0
\$\begingroup\$

C#, 80 bytes

Im checking length 4 times in this golf. i wish there was a better way to be honest.

bool f(List<int[]>a){return a.Where(m=>m.Length==a[0].Length).Count()==a.Count;}

alternative version also 80 bytes..

bool f(List<int[]>a){return a.Where(m=>m.Length==a[0].Length).SequenceEqual(a);}
\$\endgroup\$
0
\$\begingroup\$

Prolog, 40

m([],L).
m([H|T],L):-length(H,L),m(T,L).

Provide a true/false answer when calling m(X,L) for some input X.

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

APL, 13 bytes

{(×⍴⍵)↑⍵≡↓↑⍵}

Explanation:

  • ↓↑⍵: turn the list of arrays into a matrix, and then turn the matrix back into a list of arrays. Because a matrix has to be rectangular, short arrays will be padded with zeroes to match the longest.
  • ⍵≡: see if the result is equal to the input. This is only the case if no zeroes have been added, which means all the sublists were the same length.
  • ×⍴⍵: take the sign of the length of , which is 0 if is empty and 1 if not.
  • : take the first 0 or 1 items from the result depending on whether the array was empty or not.
\$\endgroup\$
  • \$\begingroup\$ Turn it into a train to save 4 bytes: ×∘⍴↑⊢≡↓∘↑. Btw, will I see you in Glasgow? \$\endgroup\$ – Adám Sep 6 '16 at 9:29
  • \$\begingroup\$ @Adám: hopefully, if nothing goes wrong, I will indeed come to Glasgow. But when you have improvements to my posts, it is better to suggest them as edits officially, that way you will get part of the reputation for subsequent upvotes. I don't want to just copy your improvements into my answers without you getting any benefit from it, it feels like cheating. \$\endgroup\$ – marinus Sep 6 '16 at 23:48
  • \$\begingroup\$ @marinus Suggesting golfing edits to an answer is against site policy. All such edits should be rejected as "causes harm" or "conflicts with author's intent". \$\endgroup\$ – mbomb007 Oct 24 '16 at 18:27
0
\$\begingroup\$

Clojure, 40 bytes

#(if(not-empty %)(apply =(map count %)))

Yay for suitable language features :)

\$\endgroup\$

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.