Побудувати сходи


26

Вступ

Я хочу побудувати сходи. Для цього я зібрав із звалища дві довгі дошки з отворами в них, і я хочу помістити сходинки в ці отвори. Однак отвори розміщені не рівномірно, тому кроки будуть трохи химерними, і мені важко оцінити кількість стержня, який мені потрібен. Ваша робота - робити розрахунки для мене.

Вхідні дані

Ваш вхід - це два бітові вектори, подані у вигляді масивів цілих чисел, які представляють дві дошки. A 0являє собою відрізок одного ауді ( довільна одиниця відстані ) без отвору, а a 1являє собою відрізок одного ауді з одним отвором. Масиви можуть бути різної довжини і містити різну кількість1 s, але вони не будуть порожніми.

Я будую свою драбину наступним чином. По-перше, я розміщую дві дошки рівно на один ауд один від одного, і вирівнюю їхні ліві кінці. Для кожного індексу iя вимірюю відстань між iотвором першої дошки з iотвором другої дошки, вирізаю шматочок стрижня і прикріплюю його між двома отворами. Я зупиняюся, як тільки в одній із дощок закінчуються дірки.

Вихідні дані

Ваш вихід - це загальна кількість стрижня, який мені знадобиться для етапів, виміряних на аудитах. Вихід повинен бути правильним принаймні до шести значущих цифр.

Приклад

Розглянемо вхідні дані [0,1,1,0,1,1,1,1,0,0]та [1,0,0,1,1,1,0,0,1]. Отримана драбина виглядає приблизно так:

Справді прикольна драбина.

Загальна довжина стрижня в цій драбині становить 7.06449510224598ауд.

Правила

Ви можете написати або функцію, або повну програму. Виграє найменший кількість байтів, а стандартні лазівки заборонені.

Випробування

[0] [0] -> 0.0
[0] [1,0] -> 0.0
[1,0,0] [1,1,1,1,1] -> 1.0
[0,1,0,1] [1,0,0,1] -> 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] -> 7.06449510224598
[1,1,1,1,1] [0,0,1,1,0,1,0,0,1] -> 12.733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1] -> 20.38177416534678

32
Для вашої безпеки я дійсно не рекомендую підніматися по будь-якій драбині, яка виглядає так.
Олексій А.

Відповіді:



10

J, 22 символи

Не натхненний відповіддю випадкових випадків. I.Частина дорівнює , як це відразу ж очевидний спосіб знаходження отворів.

(4+/@:o.<.&#$-/@,:)&I.
  • I. y- всі індекси yповторюються так само часто, як і відповідний пункт y. До речі, якщо yце вектор булевих, I. yмістить показники, на яких yє 1. Наприклад, I. 1 0 0 1 1 1 0 0 1урожайність 0 3 4 5 8.
  • x u&v y- те саме, що (v x) u (v y). Застосовується як x u&I. y, ми отримуємо (I. x) u (I. y). Давайте продовжимо перетворений вхід.
  • x <.&# y- менша довжина xі y.
  • x -/@,: y- різниця предметів xта y. Якщо один вектор довший, він оббитий нулями.
  • x $ y- yреорганізовано в формі , зазначеної x. Зокрема, якщо xце скаляр, то xелементи беруться з y. У цьому використанніx (<.&# $ -/@,:) y переконайтеся, що пропущені отвори ігноруються.
  • 4 o. y- функція %: 1 + *: y, тобто sqrt (1 + y ²). До речі, ця функція відображає від відстані отворів до довжини стрижнів.
  • +/ y- сума елементів y.

10

Пітона, 85

lambda*A:sum(abs(x-y+1j)for x,y in zip(*[[i for i,x in enumerate(l)if x]for l in A]))

Це виявилося схожим на рішення Mac . Перетворіть списки 0 і 1 в упорядковані списки одноіндексів, а потім підсумуйте відстань між відповідними елементами.


2
Чудово зроблено. Гарний трюк зі складним буквалом!
Мак

Мені трохи сумно, що це на один байт коротше моєї іншої відповіді , що, на мою думку, є більш творчим рішенням.
xnor

6

J, 32 28 байт

Дієслово I.повертає позиції 1s у двійковому рядку, що є величезною допомогою.

   +/@,@(=/&(#\)*[:>:&.*:-/)&I.

   0 1 0 1 (+/@,@(=/&(#\)*[:>:&.*:-/)&I.) 1 0 0 1
2.41421

Для кращого рішення J перевірте відповідь FUZxxl .


5

R, 67

Використовує зовнішню, щоб зробити різницю для індексованих отворів. Діаг. Повертає необхідні відмінності. Потім підсумовуйте обчислені відстані

function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5)

Тестовий запуск у R Fiddle. Я загорнув це у принт, щоб показати, що повернення відповідає специфікації.

> print((function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5))(c(0,1,1,0,1,1,1,1,0,0),c(1,0,0,1,1,1,0,0,1)),digits=10)
[1] 7.064495102
> print((function(a,b)sum((diag(outer(which(a==1),which(b==1),"-"))^2+1)^.5))(c(1,1,1,1,1),c(0,0,1,1,0,1,0,0,1)),digits=10)
[1] 12.73343313
>

Хороший. a==1може бути a>0або !!a.
freekvd

5

Haskell, 77 73 байт

r x=[a|(a,1)<-zip[1..]x]
i#j=sum$zipWith(\n m->sqrt((n-m)**2+1))(r i)$r j

Використання: [0,1,0,1] # [1,0,0,1]які виходи2.414213562373095

Як це працює: функція rповертає список положень отворів дошки, наприклад r [0,1,0,1]-> [2,4]. #перебирає два з цих списків і перетворює його на список відстаней між відповідними отворами і, нарешті, підсумовує його.


4

CJam, 36 33 байт

l~]{:L,{L=},}%z{,(},0\{~-_*)mq+}/

Дуже наївний підхід ... він очікує на введення як масиви у стилі CJam на STDIN

[0 1 1 0 1 1 1 1 0 0] [1 0 0 1 1 1 0 0 1]

Ось тестовий джгут для всіх прикладних входів. Результати в полі введення використовуються до виклику фактичного коду. Ви можете їх видалити, якщо ви мені не довіряєте. ;)

Пояснення

l~]                               "Read and eval input, wrap in an array.";
   {        }%                    "Map this block onto both input arrays.";
    :L,                           "Store array in L, get its length N.";
       {L=},                      "In the range [0 .. N-1] get all elements where L is 1.";
                                  "At this point we've converted each array into a list of its
                                   non-zero indices.";
              z                   "Transpose the array, pairing up indices at the same position.";
               {,(},              "Filter the extraneous elements of the longer input.";
                    0\            "Put a 0 before the array.";
                      {        }/ "For each pair of holes...";
                       ~-         "Unwrap the pair, take the difference.";
                         _*)mq    "Square, increment, square root.";
                              +   "Add to the running total.";

4

Пітона, 86

f=lambda a,b,i=1j:a>[]<b and a[0]*b[0]*abs(i)+f(a[a[:1]<=b:],b[b[:1]<=a:],i+a[0]-b[0])

Низькорівневе та наївне рекурсивне рішення без будь-якого пошуку списку.

Список вхідних даних є aі b. Якщо будь-який порожній, поверніться 0.

В іншому випадку, нехай xі yбути їх першими елементами (код фактично не призначати їх , тому що ви не можете зробити завдання в lambda, але це буде зробити простіше пояснити). Якщо обоє дорівнюють 1, тобто їх добуток дорівнює 1, то вони сприяють відстані стрижня. Ми відстежуємо відстань у складному числі i, так що ця відстань є абсолютною величиною. Власне, ми їх обчислюємо незалежно, а потім множимо на x*y.

Потім ми повторюємо. Ідея полягає в тому, щоб перенести обидва списки одним кроком, якщо тільки один список не починається з 0, а інший - з одного, і в цьому випадку ми зміщуємо лише список 0. Таким чином, 1-х завжди споживається парами. Ми могли б перевірити ці умови з x<yі y<x, але коротше , щоб скористатися списком порівняння як a[:1]<=b. Нарешті, ми регулюємо складне переміщення між поточними елементами на x-y.


Оскільки ви засмучені, що це на 1 байт більше, ніж ваше інше рішення, я знайшов спосіб зберегти байт. Змінити a>[]<bна a>0<b. Це працює з обох []і 0є хибними, тому вони рівноцінні.
mbomb007

Також, що таке a:?
mbomb007

1
@ mbomb007. Ви робили якісь тестування? У python2:, ([] > []) != ([] > 0)а в python3 - це помилка (нерозбірливі типи).
екхуморо

@ mbomb007. Частина a:є шматочком [b[:1]<=a:].
екхуморо

4

Python, 105 102 100 байт

i=lambda l:(i for i,h in enumerate(l)if h)
l=lambda*a:sum(((a-b)**2+1)**.5for a,b in zip(*map(i,a)))

Досить базовий, просто перетворює вхідні списки на списки індексів дірок, потім обчислює відстань між кожною парою таких індексів.

Тестовий випадок:

>>> print l([0,1,1,0,1,1,1,1,0,0], [1,0,0,1,1,1,0,0,1])
7.06449510225

Подякуйте @FryAmTheEggman за пару байтових пропозицій. Виявляється, це можна пограти в гольф далі, як продемонстровано у відповіді xnor .


Ви можете видалити пробіли після enumerate(l)та 0.5(що може бути просто .5).
FryAmTheEggman

@FryAmTheEggman: абсолютно вірно, дякую! Змінено, як було запропоновано.
Мак

Знайшов ще одну річ, використовуючи завдання із зірочкою:l=lambda*a:sum(((a-b)**2+1)**.5for a,b in zip(*map(i,a)))
FryAmTheEggman

@FryAmTheEggman: ще раз дякую! На жаль, здається, що xnor пішов один кращий, хоча - майже те саме, але з першою лямбда перекочується у другу, як розуміння списку ...
Мак

3

Pyth, 30 байт

s+0m^h^-hded2 .5CmfTm*hb@kblkQ

Спробуйте в режимі он-лайн із введенням інформації [0,1,1,0,1,1,1,1,0,0], [1,0,0,1,1,1,0,0,1].

Пояснення:

Я конвертувати списки в списки індексів [2, 3, 5, 6, 7, 8]і [1, 4, 5, 6, 9]та промайнути їх разом [(2,1), (3,4), (5,5), (6,6), (7,9)]. Потім я віднімаю значення, квадратую їх, додаю 1 і сумую над усіма квадратними коренями.

CmfTm*hb@kblkQ
 m           Q     map each list k in input() to the following list:
    m      lk         map each value b of [0, 1, 2, ..., len(k)-1] to the value:
     *hb@kb              (b + 1) * k[b]
  fT                  filter the list for positive values
C                  zip these two resulting lists

s+0m^h^-hded2 .5...
   m            ...  map each pair of values d to: 
    ^h^-hded2 .5         ((d[0] - d[1])^2 + 1)^0.5
 +0                  insert 0 at the front of the list
s                    sum

Сором, sumякий не працює для порожніх списків.


3

Пітон, 116 115 байт

Це рекурсивне рішення.

Це стало дуже прикро, коли я виявив, що index()просто видає помилку, коли значення не знайдено, але я змусив це працювати. На жаль, я не можу використовувати лямбда. Це також дратувало мене, що list.remove()не повертає список, а натомість повертається None.

def f(x,y,r=0):
    try:i,j=x.index(1),y.index(1)
    except:return r
    x.pop(i);y.pop(j);return f(x,y,r+((i-j)**2+1)**.5)

Запустити онлайн тут: http://repl.it/c5L/2


Навіть у вкладках цей код становить 116 байт, а не 112.
екхуморо

Ах, пропустили нові рядки, дякую.
mbomb007

3

Кліп 3 , 55 47 38

[cr+`j[v[w#)#mvw2B}}(c)c]sl`{%ky1%kx1`

Для списку з меншою кількістю отворів програма перебирає його і з'єднує кожну дірку з відповідним отвором іншого списку. Розміри обчислюються та підсумовуються.

>java -jar Clip3.jar ladder.clip
{0,1,1,0,1,1,1,1,0,0}
{1,0,0,1,1,1,0,0,1}
7.064495102245980096000721459859050810337066650390625

Пояснення

[c          .- Assign c to the lists, in order of size    -.
  r+`       .- The sum of...                              -.
   j[v[w    .- Join the lists with a function on v, w     -.
     #      .- Square root                                -.
      )     .- 1 plus                                     -.
       #    .- The square of                              -.
        mvw .- The distance between v and w               -.
       2
     B      .- (one-half, so #...B means square root)     -.
   }}(c)c   .- Apply joining function to the lists        -.
  ]sl`{     .- c is the (sorted by size) list of...       -.
    %ky1    .- Indices of y (the second input) which are 1-.
    %kx1    .- Indices of x (the first input) which are 1 -.
  `

Якщо ми дуже ліберальні щодо формату введення, ми можемо зменшити це до 36 байтів, видаливши кожен k. Для цього потрібно вводити рядок символів контрольних символів \0і \1.


3

ECMAScript 6, 86 байт

Спочатку це почалося з використання скорочення (я хотів побачити, чи можна це зробити в один цикл на відміну від відповіді @ edc65).

f=(c,b,a=[0,...c],j)=>a.reduce((c,v,i)=>c+=v&&(j=b.indexOf(1,j)+1,v=i-j,j)?Math.sqrt(1+v*v):0)

Але використовуючи @ edc65 для mapі &&tповернути значення, я зміг його трохи скоротити.

f=(a,b,j,c=0)=>a.map((v,i)=>c+=v&&(j=b.indexOf(1,j)+1,v=i+1-j,j)&&Math.sqrt(1+v*v))&&c

f=(a,b,j,c=0)        //variables note the j can be undefined
=>a.map((v,i)=>      //loop through the first array
c+=                  //add 
v&&                  //test to see if we have a hole
(j=b.indexOf(1,j)+1, //if so see if there is a whole on the other board
v=i+1-j,             //calculate index difference
j)                   //the last var gets evaluated so check to see if indexOf returned -1
&&Math.sqrt(1+v*v))  //calculate 
&&c                  //return sum

Мені все одно доводиться знаходити єдиний випадок, коли зменшують карту ударів за допомогою акумулятора, керованого користувачем.
edc65

@ edc65, мабуть, правда, reduceмає більше сенсу семантично, але крім того, що насправді це незручно використовувати. Звичайно, з тих пір, коли кодери в гольф турбуються про семантику.
qw3n

2

Ява, 151

Це просто ходить, aшукаючи їх, потім гуляє, bколи знайде. Якщо floatточність є прийнятною, я міг би зберегти пару байтів, але я пішов з doubleвідповідним тестовим результатом.

double d(int[]a,int[]b){double z=0;for(int x=-1,y=0,d=b.length;x++<a.length&y<d;z+=a[x]>0?Math.sqrt((y-x)*(y++-x)+1):0)for(;y<d&&b[y]<1;y++);return z;}

З пробілом:

double d(int[]a,int[]b){
    double z=0;
    for(int x=-1,y=0,d=b.length;
            x++<a.length&y<d;
            z+=a[x]>0?Math.sqrt((y-x)*(y++-x)+1):0)
        for(;y<d&&b[y]<1;y++);
    return z;
}

Шість значущих цифр є достатньою точністю, тому воно плаває, що дає вам це, продовжуйте.
Згарб

@ Zgarb Неодноразові доповнення на більшості входів дають мені лише 4-5 цифр вершини, тому я буду дотримуватися більш точної версії. Дякую за роз’яснення, хоча.
Геобіт

2

JavaScript (ES6) 108

Основним моментом є функція f, яка відображає вхідні масиви 0..1 у масивах позицій отворів. Потім скануються масиви, обчислюючи загальну довжину стержнів, використовуючи теорему піфагора. |0Ближче до кінця необхідний для перетворення NaNs , які можуть виникнути в результаті , коли масив драйвера (перший) більше , ніж другий.

F=(a,b,f=a=>a.map(v=>++u*v,u=0).filter(x=>x))=>
  f(a,b=f(b)).map((v,i)=>t+=Math.sqrt((w=b[i]-v)*w+1|0),t=0)&&t

Тест на консолі Firefox / FireBug

;[[[0],[0]]
 ,[[0],[1,0]]
 ,[[1,0,0],[1,1,1,1,1]]
 ,[[0,1,0,1],[1,0,0,1]]
 ,[[0,1,1,0,1,1,1,1,0,0],[1,0,0,1,1,1,0,0,1]]
 ,[[1,1,1,1,1],[0,0,1,1,0,1,0,0,1]]
 ,[[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0],[0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1]]]
.forEach(v=>console.log('['+v[0]+']','['+v[1]+']',F(...v)))

[0] [0] 0
[0] [1,0] 0
[1,0,0] [1,1,1,1,1] 1
[0,1,0,1] [1,0,0 , 1] 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] 7.06449510224598
[1,1, 1,1,1] [0,0,1,1,0,1,0,0,1] 12,733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1 , 1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0, 0,1,1,0,1,1,0,0,0,1] 20.38177416534678



0

Perl 98

sub l{$r=0;@a=grep$a->[$_],0..$#$a;@b=grep$b->[$_],0..$#$b;$r+=sqrt 1+(shift(@a)-shift@b)**2 while@a&&@b;$r}

Читає:

sub l {
    $r = 0;
    @a = grep $a->[$_], 0 .. $#$a;
    @b = grep $b->[$_], 0 .. $#$b;
    $r += sqrt 1 + (shift(@a) - shift @b) ** 2 while @a && @b;
    $r
}

Тестування:

use Test::More;
for (<DATA>) {
    my ($A, $B, $r) = /\[ ([0-9,]+) \] \s \[ ([0-9,]+) \] \s -> \s ([0-9.]+) /x;
    $a = [split /,/, $A];
    $b = [split /,/, $B];
    cmp_ok l(), '==', $r, "test $_";
}
done_testing($.);
__DATA__
[0] [0] -> 0.0
[0] [1,0] -> 0.0
[1,0,0] [1,1,1,1,1] -> 1.0
[0,1,0,1] [1,0,0,1] -> 2.414213562373095
[0,1,1,0,1,1,1,1,0,0] [1,0,0,1,1,1,0,0,1] -> 7.06449510224598
[1,1,1,1,1] [0,0,1,1,0,1,0,0,1] -> 12.733433128760744
[0,0,0,1,0,1,1,0,0,0,1,1,1,0,0,1,0,1,1,0,0,0,1,0] [0,0,1,1,0,1,1,1,0,0,0,0,0,1,1,0,1,1,0,0,0,1] -> 20.38177416534678

0

APL, 35 28 байт

Використовує аналогічний алгоритм до рішення J, але APL має меншу кількість вбудованих.

{+/4○⊃-/{⍵⍴¨⍨⌊/⍴¨⍵}⍵/¨⍳¨⍴¨⍵}

Приклад введення:

      {+/4○⊃-/{⍵⍴¨⍨⌊/⍴¨⍵}⍵/¨⍳¨⍴¨⍵}(1 0 0 1)(0 1 0 1)
2.414213562
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.