Look, up in the sky! It's a super duper array!

39

4

Inspired by this question from our rivals friends over at Code Review.

Definitions

A super array is an array where each new element in the array is larger than the sum of all the previous elements. {2, 3, 6, 13} is a super array because

3 > 2
6 > 3 + 2 (5)
13 > 6 + 3 + 2 (11)

{2, 3, 5, 11} is not a super array, because

3 > 2
5 == 3 + 2
11 > 5 + 3 + 2

A duper array is an array where each new element in the array is larger than the product of all the previous elements. {2, 3, 7, 43, 1856} is a super array, but it is also a duper array since

3 > 2
7 > 3 * 2 (6)
43 > 7 * 3 * 2 (42)
1856 > 43 * 7 * 3 * 2 (1806)

The challenge

Write a function or program that takes an array as input in your languages native list format, and determines how super the array is. You can also optionally take an array length input (for languages like C/C++). Also, you can assume that all of the numbers in the list will be integers greater than 0. If it's a super array, you must print It's a super array! If it is a super duper array, you must print It's a super duper array! It's also possible for an array to be duper-non-super. For example {1, 2, 3} In this case, you should print It's a duper array! If the array is neither super nor duper, you can print a falsy value.

As usual, this is code golf, so standard loopholes apply, and the shortest answer in bytes wins.

James

Posted 2016-01-19T00:00:36.077

Reputation: 54 537

9

I don't like the cumbersome I/O format, but it may be too late to change now.

– lirtosiast – 2016-01-19T02:27:20.717

1I'm sure you meant "duper-non-super" for the {1, 2, 3} array? – Darrel Hoffman – 2016-01-19T15:43:36.523

@DarrelHoffman facepalm yup, editing now. – James – 2016-01-19T15:46:49.363

1@DJMcMayhem oops, I somehow got 2 * 1 to equal 3 in my head. – Alexander Revo – 2016-01-19T20:39:55.800

4

This came up in a comment: Your spec says *If the array is neither super nor duper, you can print a falsy value.* Does this mean we must print a falsy value?

– Dennis – 2016-01-20T14:55:50.013

1Would it matter is there's 2 spaces between a word somewhere? I could still save more if super[space][space]array is allowed. – aross – 2016-01-22T11:20:34.907

Answers

20

Jelly, 47 45 4̷4̷ 42 bytes

+\,×\<ḊZṖP“sd”x;€“uper ”;/“It's a ”,“¥ṫɲ»j

This prints an empty string (falsy) for arrays that are neither super nor duper. Try it online!

How it works

+\,×\<ḊZṖP“sd”x;€“uper ”  Main link (first half). Argument: A (array)

+\                        Compute all partial sums of A.

   ×\                     Compute all partial products of A.
  ,                       Pair the results to the left and to the right.
     <Ḋ                   Perform vectorized comparison with A[1:].
                          This yields a 2D array of Booleans.
       Z                  Zip; pair the Booleans corresponding to each integer.
        Ṗ                 Remove the last pair.
                          (Nothing is compared with the last sum/product.)
         P                Take the product of each column.
          “sd”x           Perform vectorized character repetition.
                          This yields ['s', d'], ['s'], ['d'], or [].
               ;€“uper ”  Append the string "uper " to each character.


;/“It's a ”,“¥ṫɲ»j        Main link (second half).

;/                        Reduce the resulting array of strings by concatenation.
                          This will fail for an empty array, exiting immediately.
  “It's a ”,“¥ṫɲ»         Push ['It's a ', 'array!'].
                 j        Join that array, separating by the super duper string.

Dennis

Posted 2016-01-19T00:00:36.077

Reputation: 196 637

1Nice way as usual, Dennis :) Been gone for a while, time to read the Jelly docs ;) – Kade – 2016-01-19T04:28:02.790

Is there any documentation how string compression works in Jelly? – Luis Mendo – 2016-01-19T12:27:41.207

@LuisMendo Not right now. There current compression method is experimental and I'll change it soon. A quick overview: Using the indices in the code page, the compressed string is converted from bijective base 250 to integer. Each step either decodes to a printable ASCII character or a word of the dictionary, possible with changed case and/or a space before it.

– Dennis – 2016-01-19T13:56:43.187

9

JavaScript (ES6), 111 110 bytes

Saved a byte thanks to @ETHproductions!

a=>a.map((n,i)=>i&&(s=s&&n>s&&s+n,d*=d&&n>d&&n),s=d=a[0])|s|d&&`It's a ${s?"super ":""}${d?"duper ":""}array!`

Explanation

Takes an array of numbers, returns a string or the number 0 for false.

a=>
  a.map((n,i)=>      // for each number n at index i
    i&&(             // skip the first number (because s and d are initialised to it)
      s=s&&n>s&&s+n, // if it is still super and n > s, s += n, else s = false
      d*=d&&n>d&&n   // if it is still duper and n > d, d *= n, else d = false
    ),
    s=               // s = sum of previous numbers if super, else false
    d=               // d = product of previous numbers if duper, else false
      a[0]           // initialise s and d to the first number
  )
  |s|d               // if it is neither super or duper, output 0

  // Output the appropriate string
  &&`It's a ${s?"super ":""}${d?"duper ":""}array!`

Test

var solution = a=>a.map((n,i)=>i&&(s=s&&n>s&&s+n,d*=d&&n>d&&n),s=d=a[0])|s|d&&`It's a ${s?"super ":""}${d?"duper ":""}array!`
Numbers (space-separated) = <input type="text" id="input" value="2 3 7 43 1856" />
<button onclick="result.textContent=solution(input.value.split(' ').map(n=>+n))">Go</button>
<pre id="result"></pre>

user81655

Posted 2016-01-19T00:00:36.077

Reputation: 10 181

That's a clever way to do this! I think you can save two bytes with s+=s&&n>s&&n,d*=d&&n>d&&n – ETHproductions – 2016-01-19T02:32:58.920

@ETHproductions s needs to be done this way because it needs to be set to false if n>s, but d*false has the same effect so that one works. Thanks! – user81655 – 2016-01-19T02:41:46.400

5

Java, 183 182 Bytes

String w(int[]a){boolean s=1<2,d=s;int m=a[0],p=m,k=a.length,i=0,e;if(k>0)for(;++i<k;s&=e>m,d&=e>p,m+=e,p*=e)e=a[i];return d|s?"It's a "+(s?"super ":"")+(d?"duper ":"")+"array!":"";}

I made the following assumptions:

  • The output is via return value.
  • The empty String "" is a falsy value.

If any of these are wrong, please tell me.

Anyway, I can't shake the feeling that I might have gone overboard with the amount of variables.

Edit: managed to save a byte, thanks to @UndefinedFunction

ECS

Posted 2016-01-19T00:00:36.077

Reputation: 361

1Would it be possible to change boolean s=true to boolean s=1<2 ? – jrich – 2016-01-21T01:57:09.227

@UndefinedFunction Yes, good catch – ECS – 2016-01-21T08:08:34.760

4

MATL, 66 bytes

Ys5L)G6L)XK<?' super']GYp5L)K<?' duper']N?N$h'It''s a'wh' array!'h

Uses current release (10.0.3), which is earlier than this challenge.

Input is from stdin. If not super or duper, output is empty (which is falsey).

EDIT (April 7, 2016): due to changes in release 16.0.0 of the language, 5L and 6L need to be replaced by 3L and 4L repectively. The link to the online compiler includes those modifications.

Try it online!

Explanation

Ys             % implicit input. Cumulative sum
5L)            % remove last element
G6L)           % push input. Remove first element
XK             % copy to clipboard K
<?             % if all elements are smaller
  ' super'     % push string
]              % end
GYp            % push input. Cumulative product
5L)            % remove last element
K              % push input except first element
<?             % if all elements are smaller
  ' duper'     % push string
]              % end
N?             % if stack not empty
  N$h          % concatenate all elements (will be one or two strings)
  'It''s a'    % string
  wh           % prepend
  ' array!'    % string
  h            % concatenate. Implicit end. Implicit display

Luis Mendo

Posted 2016-01-19T00:00:36.077

Reputation: 87 464

3

C++14, 178, ..., 161 157 bytes

Can't think of a way to make it any shorter. Seems like there's always some room for improvement!

Update 1: I'm all for safe code, but taking a raw array and its size as function arguments is 9 bytes shorter than taking a vector :(

Update 2: Now returns an empty string as false-value, at cost of 8 bytes.

Update 3: Back to 165 bytes, thanks to CompuChip's comment.

Update 4: Another comment by CompuChip, another 4 bytes off.

Update 5: using auto instead of string along with another suggestion by CompuChip shaves another 4 bytes off the code.

auto f(int*a,int n){int s,p,d=1,e=1,r;for(s=p=*a;--n;s+=r,p*=r)r=*++a,e=r>s?e:0,d=r>p?d:0;return e|d?"It's a "s+(e?"super ":"")+(d?"duper ":"")+"array!":"";}

Ungolfed full program with test cases:

#include <iostream>
#include <string>
#include <vector>

using namespace std::literals::string_literals;

auto f(int* a, int n)
{
    int s,p,d=1,e=1,r;

    for(s=p=*a; --n; s+=r, p*=r)
        r=*++a, e=r>s?e:0, d=r>p?d:0;

    return e|d ? "It's a "s + (e?"super ":"") + (d?"duper ":"") + "array!" : "";
}

int main()
{
    std::vector<std::vector<int>> test_cases = {{2,3,6,13},
                                                {2,3,5,11},
                                                {2,3,7,43,1856},
                                                {1,2,3}
                                               };

    for(auto& test_case : test_cases)
    {
        std::cout << f(test_case.data(), test_case.size()) << '\n';
    }
}

Output:

It's a super array!

It's a super duper array!
It's a duper array!

Alexander Revo

Posted 2016-01-19T00:00:36.077

Reputation: 270

2

The string It's a array! is truthy (proof) according to our definition on Meta.

– Dennis – 2016-01-19T23:43:35.483

@Dennis actually, it's a compile error (I'm using a C++14 std::string literal, not raw character array), which is neither. Anyway, I'm updating my answer to print an empty string now, as that is the approach used in other solutions.

– Alexander Revo – 2016-01-20T07:04:47.637

1You can shave of a few more bytes if you lose the length if ... >= comparisons: I think e=r>s?e:0 is equivalent to if(r<=s)e=0. – CompuChip – 2016-01-20T09:08:14.107

@CompuChip yes indeed! The >='s were bugging me, but I didn't think of this approach to get rid of them. This also allows me to get rid of brackets in for-loop by using comma operator to separate statements and save even more bytes. Thank you. – Alexander Revo – 2016-01-20T09:23:13.337

Also, is there not some clever trick where you can use *++a instead of a[i++]? Not really up to speed with C++ and arrays. – CompuChip – 2016-01-20T13:04:38.843

@CompuChip There is, but I would still need to track if I have reached the end of the array, and I won't be able to use n for that anymore if I increment the pointer. That means I'll need another pointer and end up having code that is actually 2 bytes longer than my current version. – Alexander Revo – 2016-01-20T13:20:54.203

1@AlexanderRevo doesn't something like for(s=p=*a;--n;s+=r,p*=r)r=*++a work? Would allow you to drop i altogether – CompuChip – 2016-01-20T13:26:59.683

@CompuChip yes, it would! I did get my pointer version down to same byte count as i-version though, but, once again, your suggestion helps make it even shorter. Kinda makes me feel stupid for not seeing this. I guess I'm getting spoiled by "modern" C++ style and beginning to forget how short one can really go. – Alexander Revo – 2016-01-20T13:46:56.780

1Can't you avoid one of the increments? The one in the initializer seems unnecessary? Or does that give you one loop iteration too many? – CompuChip – 2016-01-20T14:06:02.550

@CompuChip Yes, it works fine. I just missed that spot. – Alexander Revo – 2016-01-20T14:39:56.197

2

C, 150 bytes

#define M(N,O)N(int*d,int c){return*d?*d>c?N(d+1,c O*d):0:1;}
M(S,+)M(D,*)Z(int*d){printf("It's a %s%s array!\n",S(d,0)?"super":"",D(d,0)?"duper":"");}

Each input is terminated by a 0. Test main:

#include <stdio.h>

int main() {
  int test_data[4][6] = {
    {2, 3, 7, 43, 1856, 0}, // superduper
    {2, 3, 5, 11, 0}, // not super
    {2, 3, 6, 13, 0}, // super
    {1, 2, 3, 0} // duper not super
  };

  for (int i = 0; i < 4; ++i) {
    Z(test_data[i]);
  }
}

Bonus if we are allowed a more compact output format, we can cut it to 107 bytes:

#define M(N,O)N(int*d,int c){return*d?*d>c?N(d+1,c O*d):0:1;}
M(S,+)M(D,*)Z(int*d){return S(d,0)*2^D(d,0);}

In this case, Z return 3 for superduper, 2 for super, 1 for duper and 0 for none.

Stefano Sanfilippo

Posted 2016-01-19T00:00:36.077

Reputation: 1 059

1

R, 115 bytes

function(x)cat("It's a",c("super","duper")[sapply(c(cumsum,cumprod),function(f)all(rev(x[-1]>f(x))[-1]))],"array!")

Try it online!

Falsy value: It's a array! Nothing too fancy here except maybe using sapply on a list of functions.

JayCe

Posted 2016-01-19T00:00:36.077

Reputation: 2 655

1

Pyth - 54 52 bytes

The string formatting part can probably be golfed, but I like the super-duper testing approach.

jd++"It's a"fT*V+R"uper""sd"m*F>VtQd,sMK._Q*MK"array

Test Suite.

Maltysen

Posted 2016-01-19T00:00:36.077

Reputation: 25 023

1c2"superduper" can be golfed to +R"uper""sd" – isaacg – 2016-01-19T01:28:50.667

@isaacg that's really smart – Maltysen – 2016-01-19T01:29:21.330

3You're missing the exclamation mark, I think – ETHproductions – 2016-01-19T01:47:52.577

4@TrangOul lang-pyth doesn't exist. – Dennis – 2016-01-19T14:54:59.580

2

This actually prints "It's a array" for non-super-non-duper arrays, which is a truthy string according to the definition on meta. Also, printed string should end with an exclamation mark.

– Alexander Revo – 2016-01-20T07:20:00.610

1

AWK - 140 bytes

awk 'BEGIN{d[1]=" super";e[1]=" duper";RS=" ";p=1;a=1;b=1}{a=a&&$1>s;b=b&&$1>p;s+=$1;p*=$1}END{printf "It'\''s a%s%s array!\n",d[a],e[b]}'

For those that don't know AWK, records are automatically parsed into lines based on variable RS and lines are automatically parsed into fields based on variable FS. Also unassigned variables are "" which when added to a # acts like a 0. The BEGIN section is called exactly once, before any records/fields are parsed. The rest of the language is fairly C-like with each matching code block being applied to each record. See http://www.gnu.org/software/gawk/manual/gawk.html#Getting-Started for more details.

Example run where 'code' is as above: echo 1 2 6 | 'code'

Could also place array in a file named Filename and run as: 'code' Filename

If the code is to run often it can be placed in an executable script file. This would remove the enclosing ' ' and the awk command would be placed at the top of the file as: #!/bin/awk -f

Robert Benson

Posted 2016-01-19T00:00:36.077

Reputation: 1 339

I don't know AWK, could anyone explain why this was downvoted? – Alexander Revo – 2016-01-19T21:57:19.610

Wasn't me, but I'd like an explanation of the code. Idk AWK either. – mbomb007 – 2016-01-19T22:40:55.847

This prints It's a array! for arrays that are neither super nor duper, which is a truthy string according to our definition on Meta.

– Dennis – 2016-01-19T23:40:39.517

To test try: echo 1 2 6 | <the above code> – Robert Benson – 2016-01-20T13:08:24.413

2@Dennis it's not like I'm nitpicking, but the challenge says "If the array is neither super nor duper, you can print a falsy value.", while in the other cases must is used instead. I'd say, as long as the output is clearly distinguishable from the other cases and correct, it should be fine. I'd like the word of OP on this. – Stefano Sanfilippo – 2016-01-20T14:51:51.453

I don't see very many that print anything other than It's a array! for false. Obviously something could be added, but would require a bit more code. So I too am curious about the downvote. – Robert Benson – 2016-01-20T20:39:03.793

1

Python 3, 127

Saved 5 bytes thanks to FryAmTheEggman.

Fairly basic solution right now, nothing too fancy. Just running a running total of sum and product and check each element.

def f(a):
 s=p=a[0];e=d=1
 for x in a[1:]:e&=x>s;d&=x>p;s+=x;p*=x
 return"It's a %s array!"%('super'*e+' '*e*d+'duper'*d)*(e|d)

Here's the test cases in case anyone else wants to try to beat my score.

assert f([2, 3, 6, 13]) == "It's a super array!"
assert f([2, 3, 5, 11]) == ''
assert f([2, 3, 7, 43, 1856]) == "It's a super duper array!"
assert f([1, 2, 3]) == "It's a duper array!"
print('All passed')

Morgan Thrapp

Posted 2016-01-19T00:00:36.077

Reputation: 3 574

1

PHP, 144 ... 113 112 Bytes

$x=super;$d=duper;foreach($a as$v){$v>$s||$x="";$v>$p||$d="";$s+=$v;$p=$p*$v?:$v;}echo$x.$d?"It.s a $x $d $a!":0;

Explanation:

// Initiate `$s` to prevent isset calls. Leaving this out yields PHP
// notices, but doesn't functionally change the code.
$s = 0;

// Set product to 1, so when multiplying with the first value, `$p` will
// equal `$v`.
$p = 1;

// Not existing constants `super` and `duper` yield PHP notices
// but are interpreted as strings.
$x = super;
$d = duper;

// Iterate over input (register_globals).
foreach ($a as $v) {
    // Check if current value "breaks" [sd]uper-ness: `value` not greater
    // than current sum or product. If so, unset the string.
    $v > $s || $x = "";
    $v > $p || $d = "";

    // Update sum.
    $s += $v;
    // Update product.
    $p *= $v;
}

// Check if super or duper strings are set, if so, wrap output in the
// appropriate string. Otherwise, output falsy value `0`.
echo $x . $d ? "It's a $x $d $a!" : 0;

Without register globals it would be this (118 bytes):

php -r '$x=super;$d=duper;for($p=1;$v=$argv[++$i];$p*=$v){$v>$s||$x="";$v>$p||$d="";$s+=$v;}echo$x.$d?"It.s a $x $d array!":0;' 2 3 7 43 1856 2>/dev/null;echo
  • Saved another 3 bytes by not caring about an extra space in the output
  • Saved 3 bytes by printing $a (array to string conversion yields Array)
  • Saved a byte by initializing $p to 1, so upping the product costs less.

aross

Posted 2016-01-19T00:00:36.077

Reputation: 1 583

Nice solution. A few notes: This is neither a full program nor a function as you don't handle your input $a. You don't have to worry about notices and stuff – simply ignore them on this site. – insertusernamehere – 2016-01-21T10:46:19.463

Should I replace it with $argv[1] instead? Is there a post in meta about acceptable input for PHP (or in general)? This is my first golf – aross – 2016-01-21T11:55:12.407

2

@aross Here you go. There's also this specifically about PHP but it never received a lot of attention. In general, STDIN and command-line arguments are fair game. You can also submit your code as a function.

– Martin Ender – 2016-01-21T12:36:19.920

I think going with $argv[1] is a good alternative. That being said, this challenge is very vague about it's in- and output formats. But you might be penalized on other challenges with this approach. And hard coding the input is actually not acceptable – though there are some exceptions allowing it. I know that reading input is very expensive in PHP that's why I asked a similar question on meta about it.

– insertusernamehere – 2016-01-21T12:36:45.327

My script would work with register_globals, but I'll write future golfs as a function instead. Why oh why was short_closures rejected?

– aross – 2016-01-21T13:18:36.390

Keep in mind that a function is not always the shortest solution. This is an example calculating n^2. The function version is 8 bytes longer: <?=($x=$argv[1])*$x; and function a($a){return$a*$a;}. And yes, short closures would be great. – insertusernamehere – 2016-01-21T14:15:09.893

Yeah, figured, thanks. But passing arrays as CLI argument is a PITA with PHP. You'd have to do something with explode or similar in this case. – aross – 2016-01-21T14:38:00.990

0

05AB1E, 53 51 bytes

"It's"'a„dsIη©εRćsO›}Pè.•dwā•UX¦«®εRćsP›}PiX}„¦È!ðý

Try it online or verify all test cases.

Explanation:

"It's"             # Push string "It's"
'a                 # Push string "a"
„ds                # Push string "ds"
   Iη              # Get the prefixes of the input-list
     ©             # Store it in the register (without popping)
      ε     }      # Map each sub-list to:
       R           #  Reverse the list
        ć          #  Take the head extracted
         sO        #  Swap and take the sum
           ›       #  Check if the head is larger than the sum of the rest
             P     # Then check this is truthy for all sub-lists, resulting in 0 or 1
              è    # And use this to index into the "ds" string
.•dwā•             # Push string "duper"
      U            # Store it in variable `X` (with popping unfortunately)
       X¦          # Push `X` and remove the first character
         «         # Then merge it with the "d" or "s"
®εRćsP›}P          # Do the same as explained above, but with the product instead of sum
         i }       # If this resulted in 1:
          X        #  Push variable `X` ("duper")
„¦È!               # Push string "array!"
ðý                 # Join all strings on the stack by spaces (and output implicitly)

See here for an explanation of how .•dwā• is "duper" and how „¦È! is "array!".

Kevin Cruijssen

Posted 2016-01-19T00:00:36.077

Reputation: 67 575

0

Jelly, 37 bytes

Ä,×\<ḊZṖPµ“¤ḋГ¡e⁽»x'“¡Ƈɠİ[lɦ“Ñŀṙ»jẋẸ

Try it online!

Full program.

I got the Z…P idea from Dennis's (old) answer.

Erik the Outgolfer

Posted 2016-01-19T00:00:36.077

Reputation: 38 134

0

Scala, 172 Bytes

def f(a:Seq[Int])={var q=" super"
var w=" duper"
val x=a.head
a.drop(1).foldLeft((x,x)){case ((s,p),a)=>{if(s>=a)q=""
if(p>=a)w=""
(a+s,a*p)}}
println(s"It's a $q$w array")}

Ungolfed (although there really isn't much work to do so):

def f(input:Seq[Int])={
    var super=" super"
    var duper=" duper"
    val head=input.head
    input.drop(1).foldLeft((head,head)){
        case ((sum,product),val)=>
        {
            if(sum>=val)super=""
            if(product>=val)duper=""
                (val+sum,val*product)
        }
    }
    println(s"It's a $super$duper array")
}

Ethan

Posted 2016-01-19T00:00:36.077

Reputation: 271

0

Haskell, 136 Bytes

s o t=snd.foldl(\(s,b)x->(o s x,b&&x>s))(t,1>0)
f x="It's a "++(if s(+)0x then"super "else"")++(if s(*)1x then"duper "else"")++"array!"

f is the required function. Note that the empty sum is 0 and the empty product is 1 which is why [0] is neither super nor duper.

s captures the common structure of testing super or duper by taking an arbitrary operator o and an arbitrary neutral element t. The foldr keeps track of tuples (s,b) where s is the result of chaining all seen elements with the operator o and b says whether, for every element looked at so far, this element was larger than the previously computed sum/product.

The output is not golfed very much and I would appreciate it if someone contributed a better idea!

Slightly more readable version:

s :: (Integer -> Integer -> Integer) -> Integer -> [Integer] -> Bool
s o t = snd . (foldl (\(s,b) x -> (s `o` x, b && x>s)) (t, True))

f :: [Integer] -> [Char]
f x = "It's a " ++ (if s (+) 0 x then "super " else "")
      ++ (if s (*) 1 x then "duper " else "") ++ "array!"

camelNeck

Posted 2016-01-19T00:00:36.077

Reputation: 71