Лінійне поєднання двох векторів


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, aw + by).)

У попередньому прикладі відповідна лінійна комбінація - 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 байт

Не надто вишуканий розчин пітона, який дуже щедрий накладки (використовує максимальну відстань у шаховій дошці). Введення - це один рядок, де рядки розділені трубами | (хоча алгоритм може легко використовувати все, що не буквено-цифрове, що не є новим рядком або 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] не працює в python 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]можна було знати, скільки стовпців я додав на початку кожного рядка; це дозволяє мені отримати остаточне положення символу результату. Мені все ж не байдуже, що стовпці додаються після оригінального рядка, тому другий виклик Gзаписує у нежадану комірку 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.