Линейная комбинация двух векторов


11

Управляющее резюме

Учитывая входные данные, представляющие два вектора и их соответствующие «веса», производят выходные данные, которые также представляют взвешенную сумму этих векторов.

Вызов

Ввод будет состоять из одной или нескольких строк следующих символов:

  • ровно одно вхождение цифры 0, которая представляет начало координат в двумерной плоскости;
  • ровно две другие цифры (1-9; может или не может быть одной и той же цифрой), чьи позиции относительно начала координат представляют векторы, а значения представляют веса, прикрепленные к этим векторам;
  • некоторое количество "фоновых персонажей". Решатель может выбрать определенный фоновый символ; например, я выберу "." (в основном для удобства чтения). Альтернативно, фоновые символы могут быть чем угодно, которые выглядят как пустое пространство.

(Решатель может выбрать, является ли ввод одной строкой из нескольких строк или массивом из одной строки.)

Например, вход

....2
.0...
...3.

представляет вектор с координатами (3,1) с весом 2 и вектор с координатами (2, -1) с весом 3.

Вывод должен быть почти таким же, как ввод, со следующими изменениями:

  • «символ результата», выбранный решателем, который должен быть добавлен в позиции, заданной взвешенной суммой входных векторов (эквивалентно, в позиции, которая является подходящей линейной комбинацией входных векторов);
  • столько же фоновых символов, сколько необходимо, чтобы соответствовать исходному, двум входным векторам и выходному вектору на одном и том же изображении. Дополнительные символы фона могут быть включены при желании; единственное ограничение состоит в том, что, если символ фона является видимым символом, тогда весь вывод должен быть прямоугольной формы, и каждый символ, не представляющий вектор, должен быть символом фона. (Если в качестве фоновых символов используется пустое пространство, эти ограничения применять не нужно.)

(В общем, если у нас есть один вектор (v, w) с весом a и второй вектор (x, y) с весом b, их взвешенная сумма будет a (v, w) + b (x, y) = (av +) BX, ав + с).)

В предыдущем примере подходящей линейной комбинацией является 2 * (3,1) + 3 * (2, -1) = (12, -1). Если мы используем «X» в качестве символа результата, то результат может выглядеть следующим образом

....2.........
.0............
...3.........X

или же

................
...2............
0...............
..3.........X...
................
................

Обычный выигрыш: самый короткий ответ, в байтах, выигрывает.

Пример ввода и вывода

Если используется пустое пространство, приведенный выше ввод будет выглядеть

    2
 0
   3

и результат будет выглядеть

    2
 0
   3         X

Начальные / конечные пробельные символы / строки не имеют значения; если они невидимы для читателя, это нормально. (Тем не менее, для остальных примеров я вернусь к использованию "." Для фонового символа, чтобы его было легче читать.)

Если оба вектора имеют вес 1, результат будет выглядеть как параллелограмм:

.1.
...
1.0

приводит к выходу

X.1.
....
.1.0

Обратите внимание, что этот параллелограмм может быть вырожденным, если входные векторы коллинеарны: входные

0.1..1

приводит к выходу

0.1..1.X

Возможно, чтобы вектор результата был равен одному из входных векторов или источника; в этом случае он просто перезаписывает вводимый символ. Например, вход

..2.0.1...

дает выход

..X.0.1...

(где на входе и / или выходе можно удалить начальный и конечный периоды). Вход

.....3
......
...0..
......
......
2.....

дает выход

.....3
......
...X..
......
......
2.....

Наконец, вход

90
.8

дает выход

........90
.........8
..........
..........
..........
..........
..........
..........
X.........

1
Добро пожаловать в PPCG! Хороший первый вызов.
AdmBorkBork

@TimmyD Спасибо за прием и поддержку :)
Грег Мартин,

1
Наконец, так как я уверен, что другие поднимет его, это заигрывает с проблемой хамелеона, так как значительный кусок кода будет просто анализировать входные данные, когда это не является основной задачей задачи.
AdmBorkBork

Есть ли ограничение на количество строк / столбцов на входе или правильный вывод?
Спарр

@TimmyD Я добавил общую формулу для взвешенной суммы, а также пояснил, что любой формат ввода подходит. Я согласен, что это близко к вызову хамелеона (хотя я надеялся, что некоторые языки могут иметь возможность "ходить" прямо по доске для решения проблемы); однако отзывы о Sandbox были немного более позитивными, чем негативными, поэтому я решил пойти с этим.
Грег Мартин

Ответы:


7

MATL , 48 байтов

tZyyX:UX>*Yat48-tt0>*3#fbbhb~2#fh-*s7M+'X'wZ}4$(

Фоновый символ - это пробел. Ввод - это двумерный массив символов со строками, разделенными точками с запятой. Таким образом, тестовые случаи имеют соответствующие входные данные:

['    2'; ' 0   '; '   3 ']
[' 1 '; '   '; '1 0']
['0 1  1']
['  2 0 1   ']
['     3'; '      '; '   0  '; '      '; '      '; '2     ']
['90'; ' 8']

Вывод включает в себя значительное количество пробелов.

Попробуйте онлайн!


2

Python 3, 374 355 байт

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

Изменить: Некоторые улучшения благодаря @TheBikingViking. Также добавил еще больше полей, так как я не был достаточно щедрым с отступами.

s=input()
l=[len(s),1+s.find('|')]['|'in s]
P=sorted([int(c),i%l,i//l]for i,c in enumerate(s)if c.isalnum())
L=X=Y=0
P[0][0]=-sum(p[0]for p in P)
for w,x,y in P:L=max(abs(x),abs(y),L);X+=x*w;Y+=y*w
P+=[['X',P[0][1]+X,P[0][2]+Y]]
P[0][0]=0
L=2*max(abs(X),abs(Y),L)
S=[2*L*["."]for _ in[0]*2*L]
for w,x,y in P:S[L+y][L+x]=str(w)
for s in S:print(''.join(s))

Хороший ответ! Посмотрите на советы по Python . Некоторые указания: 1. Это хорошая идея, чтобы указать, если вы использовали Python 2/3, так как некоторые функции отличаются. 2.Вы можете сделать [a,b][condition]вместо b if condition else cстроки 2. sortedпринимает любой итератор, включая оператор генератора, поэтому вы можете отбросить внешнюю пару квадратных скобок. 3. zip(p)должно работать вместо p[0] for p in P.
TheBikingViking

4. Вы можете сделать P+=[stuff]вместо P.append([stuff])строки 7. 5. Сделать ["."]вместо list("."). (3. Должно было быть zip(p)[0].)
TheBikingViking

Извините, должно быть Pв zip.
TheBikingViking

5. Вы должны быть в состоянии сделать S=[stuff]*2*Lна линии 10.
TheBikingViking

[1] Хороший вопрос, добавим версию Python. [2] Хороший шаблон, но он не будет работать index(ошибка не найдена). Будет работать с findхотя. [Re. отсортировано] Спасибо, пропустил удаление тех при добавлении sorted. [3] zip (* P) ​​[0] не работает в питоне 3 (zip-объект не индексируется). [4] P + = [материал] не будет работать, хотя P + = [[материал]] будет работать. [5] Спасибо. [другой 5] не работает. Мне нужны новые списки, а не ссылки.
Algmyr

2

JavaScript, 534 528 502 байта

n="indexOf"
J="join"
B=X=>X.split(O)
O='\n'
w=i[n](O)+1
h=B(i).length
Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}
C=[0,0,0]
G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""
o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w
x=y=0
j=i
for(z="1";z<="9";z++){while(p=~j[n](z)){j=j.replace(z," ")
x+=~p%w-l
y+=L(~p)-c}}
I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))
N=Z(I[0].length+1," ",2)
A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))
M=y+c+C[1]
O=""
m=B(A[M])
m[x+l+C[0]/h]="x"
A[M]=m[J]("")
A[J]("\n")

Обратите внимание, что заполнение является оптимальным. Эта программа предполагает, что я содержит необработанную строку со строками, разделенными \nсимволами. Заполнение выполняется пробелами, а результирующий символ - строчными x.

Это моя первая попытка игры в код.

Технические вещи: - Размер программы примерно удвоился (и его сложность резко возросла), чтобы просто учитывать символ результата, главным образом потому, что строки JavaScript являются неизменяемыми.


Построчное объяснение:

n="indexOf"
J="join"
B=X=>X.split(O)

Я часто их использую, поэтому хранение их в строках сэкономило мне место. Ниже вы можете видеть, что для splitфункции я просто создал псевдоним; это потому, что мне нужен был только один аргумент, другой был постоянным. Для indexOfи join, однако, это было бы дольше.

O='\n'
w=i[n](O)+1
h=B(i).length

Ничего сложного здесь, я читаю ширину и высоту исходного массива. Обратите внимание на использование i[n]для доступа indexOf, хотя splitобрабатывается по-разному.

Z=(X,Y,R)=>{C[R]+=X-1;return Array(X)[J](Y)}

Это становится интересным. Эта функция в основном создает сцепление J-1 раз строку X и возвращает ее. Это используется для генерации строк пробелов для заполнения.

C=[0,0,0]

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

G=(X,E,T,U,R)=>X>0&E>=0?Z(X+E+1+T,U,R):""

Эта функция одна обрабатывает заполнение (как строки, так и столбцы); на основе координаты вектора результата (X) и количества создаваемых строк / столбцов (E) он определяет необходимость его создания. X+E+1+Tэто просто уловка , чтобы сэкономить место, Uявляется строка заполнения (пространство для колонн, а целая линия для линий), и мы вернемся к R. Эта функция в основном возвращает, в случае строки, заполнение, требуемое в начале или конце указанной строки, и, в случае столбца, она возвращает строки дополнения, необходимые до или после исходных строк.

o=i[n]("0")
L=X=>Math.floor(X/(w-1))
l=L(o)
c=o%w

Здесь мы читаем позицию начала координат и получаем его координаты. L - это функция для преобразования индекса в номер строки.

x=y=0
j=i
for(z="1";z<="9";z++){
    while(p=~j[n](z)){
        j=j.replace(z," ")
        x+=~p%w-l
        y+=L(~p)-c
    }
}

Я добавил пробел, чтобы было легче читать. Здесь происходит то, что для каждого возможного числа мы продолжаем искать его в исходной строке. ~Трюк является довольно распространенным явлением в Javascript; это побитовый оператор НЕ, но здесь важно только то ~-1==0, что позволяет мне проверить конец цикла. Затем я стираю символ в строке (именно поэтому я сделал копию), что позволяет мне продолжать поиск столько, сколько необходимо. Затем я добавляю координаты вектора (x, y), используя простое вычитание.

I=B(i).map(X=>G(-x,-l,0," ",0)+X+G(x,l-w+2,0," ",2))

Здесь я делю исходную строку на строки, и для каждой строки, которую я вызываю G, генерируется заполнение до и после строк. И l-w+2так далее происходит из простого расчета индекса, который позволяет мне проверить, нужно ли мне добавлять отступы или нет. Например, если x>0и x+l-w+1>0, то (x+l-w+1)+1пробелы должны быть добавлены после строки. Объект +xудаляется из-за того, что он является первым параметром и X+E+1+Tиспользуется в определении G.

Аналогичная вещь делается для первых символов, а затем для столбцов. Здесь много факторизации, позволяющей мне использовать только одну функцию. Обратите внимание на последний параметр; в первом случае я хочу написать, чтобы C[0]позже узнать, сколько столбцов я добавил в начале каждой строки; это позволяет мне получить окончательную позицию символа результата. Однако меня не волнуют столбцы, добавленные после исходной строки, поэтому второй вызов Gwrite записывает в ненужную ячейку C[2].

N=Z(I[0].length+1," ",2)

Здесь я просто читаю новую длину строк и создаю из нее строку пробелов. Это будет использоваться для создания вертикального заполнения.

A=B(G(-y,-c,0,N+O,1)+I[J](O)+G(y,c-h,1,O+N,2))

Это точно так же, как две строки выше. Единственная разница - это запись в C[1]это время и использование разделителей N+Oи O+N. Помните, что Oэто новая Nстрока и строка пробелов. Затем я применяю Bрезультат, чтобы разделить его снова (мне нужно получить строку, содержащую символ результата, чтобы отредактировать его).

M=y+c+C[1]

Это вертикальный индекс полученного символа.

O=""
m=B(A[M])
m[x+l+C[0]/h]="x"

Здесь я вынужден изменить, Oчтобы иметь возможность разбить соответствующую строку на массив символов. Это потому, что строки JavaScript неизменны; единственный способ отредактировать строку - это преобразовать ее в массив (что я здесь и делаю), отредактировать в нужной позиции и снова присоединить строку. Также обратите внимание на hфактор, который Gвызван тем, что функция вызывается один раз для начальной строки.

A[M]=m[J]("")
A[J]("\n")

Наконец, я заменяю новую строку в массиве и снова соединяю ее в строку. Woohoo!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.