Сумма в каждом измерении


20

Вам дан многомерный массив целых чисел. Каждое измерение имеет фиксированный размер (чтобы оно всегда было прямоугольным, если оно 2D). Ваша программа должна рассчитать суммы в каждом измерении и добавить суммы в качестве новых последних элементов в этом измерении.

Предположим, что входными и выходными массивами являются A и B, а размер измерения i для A равен n i . B будет иметь то же число измерений, что и A, а размер измерения i будет n i +1. B j 1 , j 2 , ..., j m - сумма A k 1 , k 2 , ..., k m, где:

  • k i = j i, если j i <= n i
  • 0 <k i <= n i, если j i = n i +1

Для ввода:

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

Ваша программа (или функция) должна вывести:

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

Вход содержит только массив. Общее количество измерений и размер каждого измерения не указаны во входных данных. (Но вы можете получить их из массива с помощью собственного кода.) Вы можете использовать любые удобные форматы списков на вашем языке, если только они не указывают количество измерений или размеры измерений напрямую.

Вход имеет по крайней мере 1 измерение и имеет как минимум 1 элемент в массиве.

Это код-гольф. Самый короткий код выигрывает.

Контрольные примеры

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]]]]

Вы разместите это 16-байтовое решение APL? Если ты не будешь, я могу?
Денис

@ Денис Вы должны опубликовать это.
jimmy23013

Ответы:


9

J, 14 байт

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

Использование:

   ]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

Функция эквивалентна следующему, (0|:],+/)^:(#@$)но использует определяемое пользователем наречие для сохранения слов.

Объяснение последнего кода справа налево:

  • ^:(#@$)повторите ^:для количества #измерений $:

    • ],+/сцепить ,к аргументу ]с суммой его на последнее измерение+/
    • 0|:повернуть размеры |:, поместив первый 0в конец списка измерений
  • После выполнения описанной выше процедуры мы возвращаем исходный ввод с суммами по всем измерениям.

Для моего более старого решения проверьте историю изменений.

Попробуйте это онлайн здесь.


15

Mathematica, 32 20 байт

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

Пример:

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

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

Объяснение:

Полная форма {{1, 2, 3}, {4, 5, 6}}есть List[List[1, 2, 3], List[4, 5, 6]]. Затем замените все Lists в выражении на функцию ({##,+##}&).


10

Python 2, 95 байт

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

Это перебирает все измерения, объединяя их суммы, используя NumPy.

Я наткнулся на NumPy r_, что довольно здорово для игры в гольф. r_[:n]короче range(n)и намного мощнее (например r_[:4, 7, 8, 10:100:10]). Он также может выполнять другие функции, такие как конкатенация по произвольной оси.

Пример использования:

$ 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 байт

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

Спасибо @ user23013 за вывод 3 байта и определение правильного формата ввода.

Проверьте контрольные примеры онлайн с TryAPL .

идея

Общая идея та же, что и в моем представлении CJam, для которого APL допускает гораздо более короткую реализацию. Он состоит всего из двух шагов:

  1. Суммируйте массив по его внешнему измерению.

  2. Повторите шаг 1 для каждого подмассива.

Код

{             } ⍝ 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 ⍵.

Просто выяснил формат ввода для вашего исходного кода: ,⊂(,1)(,1)(,1)(,0)и ,⊂,⊂,⊂,¯1соответственно. Таким образом, вы можете удалить другого персонажа.
jimmy23013

2
@ user23013: Мой код работал! Вы должны любить язык программирования, где формат ввода сложнее понять, чем реальный код ...
Деннис

6

Пип , 18 15 байт

{a-a?fMaAE$+aa}

Это анонимная функция, которая принимает массив в качестве аргумента и возвращает результат. Пример вызова с использованием -pфлага для получения читабельного вывода:

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]]

Идея в основном такая же, как и у Денниса , но независимо полученная. Более конкретно:

{             }  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

Этот метод работает, потому что +(наряду со многими другими операторами) функционирует поэтапно в списках в Pip - функция, основанная на языках программирования массивов, таких как APL. Поэтому, когда вам $+нравится список [[1 2 3] [4 5 6]], результат будет [5 7 9]желаемым. Также используется в тесте со списком или скаляром: [1 2 3] - [1 2 3]дает [0 0 0], что верно (как и все списки, кроме пустого списка).

Предыдущая 18-байтовая версия:

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

Изменения:

  1. Сохраненный байт в тесте скаляр или список - предыдущий метод состоял в том, чтобы соединить аргумент (в пустой строке) и проверить, равен ли он самому не присоединенному (работает, потому что [1 2 3] != 123);
  2. Устранены скобки. Они необходимы в оригинале, потому что Mимеют более низкий приоритет, чем ?(хотя я, вероятно, собираюсь это изменить, особенно сейчас): без них код будет анализироваться как (Ja=a?af)M(aAE$+a), что приведет к причудливым сообщениям об ошибках. Тем не менее, средний аргумент троичного оператора может быть любым выражением любого приоритета, без скобок. Таким образом, сделав список правдивым, я могу сохранить эти два байта.

2
Это интересный язык у вас там. Поэтапные операторы - это то, чего не хватает в CJam и Pyth.
Деннис

@ Деннис Спасибо! Эта работа все еще находится в стадии разработки, но есть некоторые задачи, с которыми она справляется.
DLosc

5

APL (25)

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

Массивы APL имеют встроенные измерения, так что это функция, которая принимает n- мерный массив и затем суммирует по каждому измерению.

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

Объяснение:

  • N←⍵: сохранить массив в N.
  • ⍴⍴N: получить количество измерений N. ( дает размеры, т.е. ⍴↑(1 2 3)(4 5 6)дает 2 3, поэтому ⍴⍴дает размеры измерений.)
  • {... }¨⍳: для каждого номера от 1 до ⍴⍴N:
    • +/[⍵]N: сумма Nпо измерению
    • N,[⍵]←: присоединить результат к Nв этом измерении
  • N: наконец, вернитесь N.

Я не могу заставить эту работу работать, если массив содержит синглтоны. Как бы вы назвали эту функцию для третьего или четвертого теста?
Деннис

3
@Dennis: вам нужно передать функцию многомерного массива. То, что ↑(1 2 3)(4 5 6)делает, это просто строит 2-мерный массив из 2 1-мерных, используя . Это не встроенная запись, и она не обобщает то, как вы могли бы думать. Канонический способ построения 3-го и 4-го массивов был бы 1 4 1⍴1 1 1 0и 1 1 1 1⍴¯1, но также возможно построить их без ссылки на размеры, например, третий массив также может быть ↑⍉⍪(,1)(,1)(,1)(,0)создан с , четвертый может быть создан с ↑⍪⊂⍪¯1.
марин

ОК, это все объясняет. Моя наивная реализация рекурсивного подхода хорошо работает для того, что я считал массивами (например f←{0=≡⍵:⍵⋄f¨⍵,+/⍵}⋄f((1 2)(3 4))((5 6)(7 8))), но кажется, что вложенные векторы и массивы отличаются, и первый не отличает скаляры от синглетонов ...
Деннис

2
@Dennis Golfed: {×≡⍵:∇¨⍵,+/⍵⋄⍵}((1 2)(3 4))((5 6)(7 8)). Исправлено: {×⍴⍴⍵:∇↓⍵,+/⍵⋄⍵}1 4 1⍴1 1 1 0. Теперь он короче, чем Mathematica ...
jimmy23013

3

CJam, 36 байт

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

Это рекурсивная именованная функция, которая извлекает массив из стека и оставляет один взамен.

Попробуйте тестовые случаи в интерпретаторе CJam .

идея

К сожалению, в CJam нет некоторого автоматического оператора, который позволяет добавлять произвольно вложенные массивы, поэтому мы должны реализовать его самостоятельно. К счастью, это делает два инфиксных оператора, :(уменьшить) и. (векторизируют), которые окажутся полезными для этой задачи.

Шаг первый - вычисление количества измерений. Это легко: преобразовать массив в его строковое представление и посчитать количество ведущих [ 's.

Теперь, чтобы уменьшить массив из одного измерения, вы обычно просто выполняете :+:

[1 2] :+ e# Pushes 3.

Для массива двух измерений +будет выполнять конкатенацию вместо сложения, поэтому мы должны векторизовать его:

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

Теперь для массива из трех измерений он .+будет работать с массивами из двух измерений и снова выполнять конкатенацию. На этот раз мы должны векторизовать .+:

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

Для общего случая, массива размерности D , мы должны объединить в цепочку один :, D - 1 . и один +.

Конечно, это только суммирует массив только через его крайнее измерение. Мы можем решить это, определив функцию S которая вычисляет размерность (и ничего не делает, если она равна нулю), выполняет сумму, как указано выше, и, наконец, применяет себя к элементам массива.

Код

{                                }: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

Рубин ( 181 139 119 108 байт)

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

Предполагается, что ввод передается как JSON.


И на самом деле вы можете просто написать функцию, которая принимает проанализированный массив и возвращает массив, и dв этом ответе учитывается только 95 байтов .
jimmy23013

2

Java, 669 байт

не буду врать, я очень горжусь собой за это: 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;}}

расширен с тестированием:

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();
    }

}

запуск расширенной тестовой версии печатает это:

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 для расширенной версии, строка: Array.set (result, x, sum (Array.get (arrayA, x), Array.get (arrayB, x ++))); в методе _sum (...) должен был быть вызван _sum (...), а не sum (...). мой плохой
Джек Боеприпасы
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.