9
\$\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\$
18
  • 1
    \$\begingroup\$ what if we can't return different types (Arrays / Booleans)? \$\endgroup\$
    – nimi
    Jun 9, 2016 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, 2016 at 22:14
  • 1
    \$\begingroup\$ Are the sublist elements always going to be positive integers? \$\endgroup\$
    – Neil
    Jun 9, 2016 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, 2016 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\$ Jun 10, 2016 at 7:31

25 Answers 25

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\$
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\$
2
  • \$\begingroup\$ I think ?QqCC works. \$\endgroup\$ Jun 9, 2016 at 21:19
  • \$\begingroup\$ @FryAmTheEggman nice! \$\endgroup\$
    – Maltysen
    Jun 9, 2016 at 21:20
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\$
0
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\$
7
  • \$\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, 2016 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, 2016 at 23:33
  • 1
    \$\begingroup\$ "Somehow" == in JavaScript [].toString() returns an empty string. \$\endgroup\$
    – traktor
    Jun 10, 2016 at 0:18
  • \$\begingroup\$ Array.prototype.toString() is equivalent to Array.prototype.join() with no arguments, that's why. \$\endgroup\$ Jun 10, 2016 at 3:57
  • \$\begingroup\$ Try wrapping the array in JSON.stringify to display it correctly. \$\endgroup\$ Jun 10, 2016 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\$
2
  • \$\begingroup\$ Is the initial space required? \$\endgroup\$ Jun 10, 2016 at 0:40
  • \$\begingroup\$ Nope, that was just a typo. It wasn't in my letter count anyway \$\endgroup\$
    – Alexander
    Jun 10, 2016 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\$
7
  • \$\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, 2016 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, 2016 at 22:17
  • \$\begingroup\$ why does it do that? shouldn't it return c if b is true? \$\endgroup\$
    – Maltysen
    Jun 9, 2016 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, 2016 at 22:21
  • \$\begingroup\$ oic, can you do instead then {}&&stuff? \$\endgroup\$
    – Maltysen
    Jun 9, 2016 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\$
2
  • \$\begingroup\$ Looks like can drop the parens around h:t. \$\endgroup\$
    – Lynn
    Jun 23, 2016 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, 2016 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\$
8
  • 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, 2016 at 9:15
  • \$\begingroup\$ @Frozn Ah, you're completely right, I screwed up!.. I've removed it. Thanks. \$\endgroup\$ Jun 10, 2016 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, 2016 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, 2016 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, 2016 at 19:02
1
\$\begingroup\$

Python, 45 bytes

lambda x:x and min(x,key=len)==max(x,key=len)
\$\endgroup\$
4
  • 2
    \$\begingroup\$ 5 bytes shorter: f=lambda x:x and len(set(map(len,x)))<2 \$\endgroup\$
    – Maltysen
    Jun 9, 2016 at 21:36
  • \$\begingroup\$ also, yours doesn't work on [] \$\endgroup\$
    – Maltysen
    Jun 9, 2016 at 21:37
  • \$\begingroup\$ You should return the array if it's empty. \$\endgroup\$
    – ospahiu
    Jun 9, 2016 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, 2016 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\$
2
  • \$\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, 2016 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, 2016 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\$
3
  • \$\begingroup\$ Turn it into a train to save 4 bytes: ×∘⍴↑⊢≡↓∘↑. Btw, will I see you in Glasgow? \$\endgroup\$
    – Adám
    Sep 6, 2016 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, 2016 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, 2016 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 and acknowledge you have read our privacy policy.

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