Somme dans chaque dimension


20

Vous obtenez un tableau multidimensionnel d'entiers. Chaque dimension a une taille fixe (de sorte qu'elle serait toujours rectangulaire si elle est 2D). Votre programme doit calculer les sommes dans chaque dimension et les ajouter en tant que nouveaux derniers éléments de cette dimension.

Supposons que les tableaux d'entrée et de sortie sont A et B, et que la taille de la dimension i de A est n i . B aurait le même nombre de dimensions que A et la taille de la dimension i serait n i +1. B j 1 , j 2 , ..., j m est la somme de A k 1 , k 2 , ..., k m où:

  • k i = j i si j i <= n i
  • 0 <k i <= n i si j i = n i +1

Pour l'entrée:

[[1 2 3]
 [4 5 6]]

Votre programme (ou fonction) devrait produire:

[[1 2 3 6]
 [4 5 6 15]
 [5 7 9 21]]

L'entrée contient uniquement le tableau. Le nombre total de dimensions et la taille de chaque dimension ne sont pas indiqués dans l'entrée. (Mais vous pouvez les obtenir à partir du tableau par votre propre code.) Vous pouvez utiliser n'importe quel format de liste pratique dans votre langue, tant qu'il ne spécifie pas directement le nombre de dimensions ou les tailles de dimension.

L'entrée a au moins 1 dimension et a au moins 1 élément dans le tableau.

C'est du code-golf. Le code le plus court gagne.

Cas de test

Input:
[5 2 3]
Output:
[5 2 3 10]

Input:
[[1 2 3] [4 5 6]]
Outputs:
[[1 2 3 6] [4 5 6 15] [5 7 9 21]]

Input:
[[[1] [1] [1] [0]]]
Output:
[[[1 1] [1 1] [1 1] [0 0] [3 3]] [[1 1] [1 1] [1 1] [0 0] [3 3]]]

Input:
[[[[-1]]]]
Output:
[[[[-1 -1] [-1 -1]] [[-1 -1] [-1 -1]]] [[[-1 -1] [-1 -1]] [[-1 -1] [-1 -1]]]]

Publierez-vous cette solution APL de 16 octets? Si vous ne le faites pas, je peux?
Dennis

@Dennis Vous devez le poster.
jimmy23013

Réponses:


9

J, 14 octets

#@$(0|:],+/^:)

Usage:

   ]a=.i.2 3
0 1 2
3 4 5

   (#@$(0|:],+/^:)) a    NB. parens are optional
0 1 2  3
3 4 5 12
3 5 7 15

La fonction est équivalente à la suivante (0|:],+/)^:(#@$)mais utilise un adverbe défini par l'utilisateur pour enregistrer les parens.

Explication de ce dernier code de droite à gauche:

  • ^:(#@$)répéter ^:pour le nombre #de dimensions $:

    • ],+/concaténer ,l'argument ]avec la somme de celui-ci sur la dernière dimension+/
    • 0|:faire pivoter les dimensions |:en plaçant la première 0à la fin de la liste de dimensions
  • Après avoir effectué la procédure ci-dessus, nous récupérons l'entrée d'origine avec des sommes sur toutes les dimensions.

Pour mon ancienne solution, consultez l'historique des révisions.

Essayez-le en ligne ici.


15

Mathematica, 32 20 octets

#/.List->({##,+##}&)&

Exemple:

In[1]:= #/.List->({##,+##}&)&[{{1, 2, 3}, {4, 5, 6}}]

Out[1]= {{1, 2, 3, 6}, {4, 5, 6, 15}, {5, 7, 9, 21}}

Explication:

La forme complète de {{1, 2, 3}, {4, 5, 6}}est List[List[1, 2, 3], List[4, 5, 6]]. Remplacez ensuite tous les Lists de l'expression par la fonction ({##,+##}&).


10

Python 2, 95 octets

from numpy import*
a=copy(input())
for d in r_[:a.ndim]:a=r_[`d`,a,sum(a,d,keepdims=1)]
print a

Cela itère sur chaque dimension, concaténant ses sommes à l'aide de NumPy.

Je suis tombé sur NumPy's r_, ce qui est assez génial pour le golf. r_[:n]est plus court range(n)et beaucoup plus puissant (par exemple r_[:4, 7, 8, 10:100:10]). Il peut également faire d'autres choses comme la concaténation le long d'un axe arbitraire.

Exemple d'utilisation:

$ python sum.py
[[1, 2, 3], [4, 5, 6]]
[[ 1  2  3  6]
 [ 4  5  6 15]
 [ 5  7  9 21]]

7

APL, 16 15 octets

{×≡⍵:∇¨⍵,+/⍵⋄⍵}

Merci à @ user23013 d'avoir joué sur 3 octets et d'avoir trouvé le bon format d'entrée.

Vérifiez les cas de test en ligne avec TryAPL .

Idée

L'idée générale est la même que dans mon mémoire CJam, pour lequel APL permet une mise en œuvre beaucoup plus courte. Il ne comprend que deux étapes:

  1. Additionnez le tableau sur sa dimension la plus à l'extérieur.

  2. Répétez l'étape 1 pour chaque sous-réseau.

Code

{             } ⍝ Define a monadic function with argument ⍵ and reference ∇.
 ×≡⍵:           ⍝ If the depth of ⍵ is positive:
     ∇          ⍝   Apply this function...
      ¨         ⍝   to each element of...
       ⍵,       ⍝   the concatenation of ⍵...
         +/⍵    ⍝   and the sum across ⍵.
            ⋄⍵  ⍝  Else, return ⍵.

Je viens de découvrir le format d'entrée pour votre code d'origine: ,⊂(,1)(,1)(,1)(,0)et ,⊂,⊂,⊂,¯1respectivement. Vous pouvez donc supprimer un autre personnage.
jimmy23013

2
@ user23013: Mon code a donc fonctionné! Il faut aimer un langage de programmation où le format d'entrée est plus difficile à obtenir correctement que le code réel ...
Dennis

6

Pip , 18 15 octets

{a-a?fMaAE$+aa}

Il s'agit d'une fonction anonyme, qui prend le tableau en argument et renvoie le résultat. Exemple d'appel, en utilisant l' -pindicateur pour obtenir une sortie lisible:

C:\> pip.py -pe "( {a-a?fMaAE$+aa} [[1 2 3] [4 5 6]] )"
[[1;2;3;6];[4;5;6;15];[5;7;9;21]]

L'idée est fondamentalement la même que l'APL de Dennis , bien que dérivée indépendamment. Plus précisement:

{             }  Define a lambda function with parameter a
 a-a?            Shortest way I could find to test whether the argument is a list
                 or scalar: subtracting a number from itself gives 0 (falsy);
                 subtracting a list from itself gives a list of zeros (truthy!)
     fM          If truthy, it's a list, so map the same function (f) recursively to:
       aAE         Argument, with appended element...
          $+a      ...sum of argument (fold on +)
             a   If falsy, it's a scalar, so just return it

Cette méthode fonctionne parce que +(avec de nombreux autres opérateurs) fonctionne par élément sur les listes dans Pip - une fonctionnalité inspirée des langages de programmation de tableaux comme APL. Ainsi, lorsque vous $+une liste comme [[1 2 3] [4 5 6]], le résultat est [5 7 9]comme vous le souhaitez. Également utilisé dans le test de liste ou scalaire: [1 2 3] - [1 2 3]donne[0 0 0] , qui est véridique (comme toutes les listes sauf la liste vide).

Version précédente de 18 octets:

{Ja=a?a(fMaAE$+a)}

Changements:

  1. Enregistrement d'un octet sur le test scalaire ou de liste - la méthode précédente consistait à joindre l'argument (sur une chaîne vide) et à tester s'il était égal à son soi non joint (fonctionne parce que [1 2 3] != 123 );
  2. Éliminé les parenthèses. Ils sont nécessaires dans l'original car ils ont Mune priorité inférieure à ?(bien que je vais probablement changer cela, surtout maintenant): sans eux, le code serait analysé comme (Ja=a?af)M(aAE$+a), conduisant à des messages d'erreur bizarres. Cependant, l'argument du milieu d'un opérateur ternaire peut être n'importe quelle expression de n'importe quelle priorité, sans parenthèses nécessaires. Donc, en faisant de la liste le cas vrai, je peux enregistrer ces deux octets.

2
C'est une langue intéressante que vous avez obtenue. Les opérateurs par élément sont ce qui manque dans CJam et Pyth.
Dennis

@Dennis Merci! C'est toujours un travail en cours, mais il y a des tâches avec lesquelles il se débrouille assez bien.
DLosc

5

APL (25)

{N⊣{N,[⍵]←+/[⍵]N}¨⍳⍴⍴N←⍵}

Les tableaux d'APL ont des dimensions intégrées, c'est donc une fonction qui prend un tableau à n dimensions, puis additionne le long de chaque dimension.

      {N⊣{N,[⍵]←+/[⍵]N}¨⍳⍴⍴N←⍵} ↑(1 2 3)(4 5 6)
1 2 3  6
4 5 6 15
5 7 9 21

Explication:

  • N←⍵: stocker le tableau dans N.
  • ⍴⍴N: obtenez le nombre de dimensions Na. ( donne les dimensions, c'est-à-dire ⍴↑(1 2 3)(4 5 6)donne 2 3, donc ⍴⍴donne les dimensions des dimensions.)
  • {... }¨⍳: pour chaque nombre de 1 à ⍴⍴N:
    • +/[⍵]N: somme le Nlong de la dimension
    • N,[⍵]←: joindre le résultat à Ndans cette dimension
  • N: enfin, revenez N.

Je n'arrive pas à faire ce travail si le tableau contient des singletons. Comment appelleriez-vous cette fonction pour le troisième ou le quatrième scénario de test?
Dennis

3
@Dennis: vous devez transmettre à la fonction un tableau multidimensionnel. Ce que ↑(1 2 3)(4 5 6)fait est simplement de construire un tableau à 2 dimensions à partir de 2 à 1 dimensions en utilisant . Ce n'est pas une notation intégrée et elle ne généralise pas la façon dont vous pourriez penser. La manière canonique de construire les 3e et 4e tableaux serait 1 4 1⍴1 1 1 0et 1 1 1 1⍴¯1, mais il est également possible de les construire sans se référer aux tailles, par exemple, le troisième tableau peut également être construit avec ↑⍉⍪(,1)(,1)(,1)(,0), le quatrième peut être construit avec ↑⍪⊂⍪¯1.
marinus

OK, ça explique tout. Ma mise en œuvre naïve d'une approche récursive fonctionne bien pour ce que je pensais être des tableaux (par exemple f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), mais il semble que les vecteurs et les tableaux imbriqués sont différents et que le premier ne différencie pas les scalaires des singletons ...
Dennis

2
@Dennis golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Correction: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. C'est plus court que Mathematica maintenant ...
jimmy23013

3

CJam, 36 octets

{_`{'[<}#:D{_":"D'.e]'++~a+{S}%}&}:S

Il s'agit d'une fonction nommée récursive qui extrait un tableau de la pile et en laisse un en retour.

Essayez les cas de test dans l' interpréteur CJam .

Idée

Malheureusement, CJam n'a pas d'opérateur automagique qui permet d'ajouter des tableaux imbriqués arbitrairement, nous devons donc l'implémenter nous-mêmes. Heureusement, cela fait que deux opérateurs infixes, :(réduire) et. (vectoriser), qui s'avéreront utiles pour cette tâche.

La première étape consiste à calculer le nombre de dimensions. C'est simple: convertissez le tableau en sa représentation sous forme de chaîne et comptez le nombre de [ .

Maintenant, pour réduire un tableau d'une dimension, vous exécutez généralement simplement :+:

[1 2] :+ e# Pushes 3.

Pour un tableau à deux dimensions, +effectuerait la concaténation au lieu de l'addition, nous devons donc le vectoriser:

[[1 2][3 4]] :.+ Pushes [4 6].

Maintenant, pour un tableau de trois dimensions, .+fonctionnerait sur des tableaux de deux dimensions et effectuerait, encore une fois, la concaténation. Cette fois, nous devons vectoriser .+:

[[[1 2][3 4]][[5 6][7 8]]] :..+ e# Pushes [[[6 8] [10 12]]].

Pour le cas général, un tableau de dimension D , nous devons enchaîner un :, D - 1 . et un +.

Bien sûr, cela ne résume le tableau que dans sa dimension la plus éloignée. On peut résoudre cela en définissant une fonction S qui calcule la dimension (et ne fait rien si elle est nulle), effectue la somme comme indiqué ci-dessus et, enfin, s'applique aux éléments du tableau.

Code

{                                }:S e# Define S:
 _`                                  e#   Push a string representation of a the array.
   {'[<}#                            e#   Find the index of the first non-bracket.
         :D                          e#   Save it in D.
           {                   }&    e#   If D is positive:
            _                        e#     Push a copy of the array.
             ":"D'.e]                e#     Pad ":" with "."s to a string of length D.
                     '++~            e#     Add a "+" to the string and evaluate.
                         a+          e#     Wrap the result in a array and concatenate.
                           {S}%      e#     Apply S to the elements of the array.

2

Rubis ( 181 139 119 119 108 octets)

def d a;a.push a[0].to_s['[']?a.map{|x|d x}.transpose.map{|x|x.reduce:+}:a.reduce(:+)end
p d eval ARGF.read

Suppose que l'entrée est passée en JSON.


Et en fait, vous pouvez simplement écrire une fonction acceptant un tableau analysé et renvoyant un tableau, et ne compter que les 95 octets ddans cette réponse.
jimmy23013

2

Java, 669 octets

ne va pas mentir, je suis assez fier de moi pour celui-ci: p

import java.lang.reflect.Array;enum S{D;<A>A s(A a){int l=Array.getLength(a),x=0;Class t=a.getClass();Class c=t.getComponentType();A r=(A)Array.newInstance(c,l+1);System.arraycopy(a,0,r,0,l);if(t==int[].class)for(;x<l;)((int[])r)[l]=((int[])r)[l]+((int[])r)[x++];else{for(;x<l;)Array.set(r,x,S.this.s(Array.get(r,x++)));Object o=Array.get(r,0);for(;--x>0;)o=s(o,Array.get(r,x));Array.set(r,l,o);}return r;}<A>A s(A a,A b){int l=Array.getLength(a),x=0;Class t=a.getClass();A r=(A)Array.newInstance(t.getComponentType(),l);if(int[].class==t)for(;x<l;)((int[])r)[x]=((int[])a)[x]+((int[])b)[x++];else for(;x<l;)Array.set(r,x,s(Array.get(a,x),Array.get(b,x++)));return r;}}

élargi avec des tests:

import java.lang.reflect.Array;
import java.util.Arrays;

public enum SumOf{
    Dimensions;

    <A>A sum(A array){ //call this method to solve the challenge
        int length=Array.getLength(array),x=0;
        Class arrayType=array.getClass();
        Class componentType=arrayType.getComponentType();
        //grow the array to include the sum element
        A result=(A)Array.newInstance(componentType,length+1);
        System.arraycopy(array,0,result,0,length);
        if(arrayType==int[].class) //one-dimensional array needs to be handled separately
            for(;x<length;) //find the sum
                ((int[])result)[length]=((int[])result)[length]+((int[])result)[x++];        
        else{ //multi-dimensional array
            for(;x<length;) //find the sum for each element in this dimension's array
                Array.set(result,x,sum(Array.get(result,x++)));
            //find the total sum for this dimension's array
            Object s=Array.get(result,0);
            for(;--x>0;)
                s=_sum(s,Array.get(result,x)); //add the 2 elements together
            Array.set(result,length,s);
        }
        return result;
    }

    <A>A _sum(A arrayA,A arrayB){ //this method is used by the previous method
        int length=Array.getLength(arrayA),x=0;
        Class arrayType=arrayA.getClass();
        A result=(A)Array.newInstance(arrayType.getComponentType(),length);
        if(int[].class==arrayType) //one-dimensional array needs to be handled separately
            for(;x<length;) //find the sum of both arrays
                ((int[])result)[x]=((int[])arrayA)[x]+((int[])arrayB)[x++];
        else
            for(;x<length;) //find the sum of both arrays
                Array.set(result,x,sum(Array.get(arrayA,x),Array.get(arrayB,x++)));
            return result;
        }

    static int[] intArray( int firstElement, int...array ) {
        if( array == null ) array = new int[0];
        array = Arrays.copyOf( array, array.length + 1 );
        System.arraycopy( array, 0, array, 1, array.length - 1 );
        array[0] = firstElement;
        return array;
    }

    static <E> E[] arrayArray( E firstElement, E...array ) {
        if( array == null ) array = (E[]) Array.newInstance( firstElement.getClass(), 0 );
        array = Arrays.copyOf( array, array.length + 1 );
        System.arraycopy( array, 0, array, 1, array.length - 1 );
        array[0] = firstElement;
        return array;
    }

    static void printIntArray( int[]array ){
        System.out.print("[ ");
        for( int x = 0; x < array.length; x++ )
            System.out.print( array[x] + " " );
        System.out.print("] ");
    }

    static < A > void printArray( A array ) {
        if( array.getClass() == int[].class ){
            printIntArray( (int[]) array );
        }
        else {
            System.out.print("[ ");
            int length = Array.getLength( array );
            for( int x = 0; x < length; x++ )
                printArray( Array.get( array, x ) );
            System.out.print("] ");
        }
    }

    public static void main(String[]s){
        int[] test01 = intArray( 5, 2, 3 );
        System.out.print("Input: ");
        printArray( test01 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test01 ) );
        System.out.println();

        int[][] test02 = arrayArray( intArray( 1, 2, 3 ), intArray( 4, 5, 6 ) );
        System.out.print("\nInput: ");
        printArray( test02 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test02 ) );
        System.out.println();

        int[][][] test03 = arrayArray( arrayArray( intArray( 1 ), intArray( 1 ), intArray( 1 ), intArray( 0 ) ) );
        System.out.print("\nInput: ");
        printArray( test03 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test03 ) );
        System.out.println();

        int[][][][] test04 = arrayArray( arrayArray( arrayArray( intArray( -1 ) ) ) );
        System.out.print("\nInput: ");
        printArray( test04 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test04 ) );
        System.out.println();

        int[][][] test05 = arrayArray( arrayArray( intArray( 1, 2, 3 ), intArray( 4, 5, 6 ), intArray( 7, 8, 9 ) ), arrayArray( intArray( 11, 12, 13 ), intArray( 14, 15, 16 ), intArray( 17, 18, 19 ) ), arrayArray( intArray( 21, 22, 23 ), intArray( 24, 25, 26 ), intArray( 27, 28, 29 ) ) );
        System.out.print("\nInput: ");
        printArray( test05 );
        System.out.print("\nOutput: ");
        printArray( SumOf.Dimensions.sum( test05 ) );
        System.out.println();
    }

}

l'exécution de la version de test étendue imprime ceci:

Input: [ 5 2 3 ] 
Output: [ 5 2 3 10 ] 

Input: [ [ 1 2 3 ] [ 4 5 6 ] ] 
Output: [ [ 1 2 3 6 ] [ 4 5 6 15 ] [ 5 7 9 21 ] ] 

Input: [ [ [ 1 ] [ 1 ] [ 1 ] [ 0 ] ] ] 
Output: [ [ [ 1 1 ] [ 1 1 ] [ 1 1 ] [ 0 0 ] [ 3 3 ] ] [ [ 1 1 ] [ 1 1 ] [ 1 1 ] [ 0 0 ] [ 3 3 ] ] ] 

Input: [ [ [ [ -1 ] ] ] ] 
Output: [ [ [ [ -1 -1 ] [ -1 -1 ] ] [ [ -1 -1 ] [ -1 -1 ] ] ] [ [ [ -1 -1 ] [ -1 -1 ] ] [ [ -1 -1 ] [ -1 -1 ] ] ] ] 

Input: [ [ [ 1 2 3 ] [ 4 5 6 ] [ 7 8 9 ] ] [ [ 11 12 13 ] [ 14 15 16 ] [ 17 18 19 ] ] [ [ 21 22 23 ] [ 24 25 26 ] [ 27 28 29 ] ] ] 
Output: [ [ [ 1 2 3 6 ] [ 4 5 6 15 ] [ 7 8 9 24 ] [ 12 15 18 45 ] ] [ [ 11 12 13 36 ] [ 14 15 16 45 ] [ 17 18 19 54 ] [ 42 45 48 135 ] ] [ [ 21 22 23 66 ] [ 24 25 26 75 ] [ 27 28 29 84 ] [ 72 75 78 225 ] ] [ [ 33 36 39 108 ] [ 42 45 48 135 ] [ 51 54 57 162 ] [ 126 135 144 405 ] ] ] 

erm pour la version étendue, la ligne: Array.set (result, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); dans la méthode _sum (...) aurait dû appeler _sum (...), pas sum (...). mon mauvais
Jack Ammo
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.