Порахуйте зміни в масиві


20

Ваше завдання сьогодні - написати програму або функцію, яка займає масив цілих чисел, і підраховує кількість разів, читаючи її зліва направо, щоб значення змінювалося. Це простіше показати на прикладі:[1 1 1 2 2 5 5 5 5 17 3] => [1 1 1 **2** 2 **5** 5 5 5 **17** **3**] => 4

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

Input           |   Output
[]              |   0
[0]             |   0
[0 1]           |   1
[0 0]           |   0
[1 2 3 17]      |   3
[1 1 1 2 2 3]   |   2
[-3 3 3 -3 0]   |   3

Це , найменше виграш байтів!


Чи правильна моя відповідь, якщо результат завжди правильно розрахований, але якщо він Falseдорівнює 0, друкується замість цього?
FlipTack

1
@FlipTack Це залежить від мови. Взагалі, якщо я можу сказати, 2+Falseі це помилки, це не добре, але якщо я отримаю 2, це добре.
Павло

@FlipTack За замовчуванням це консенсус.
повністюлюдсько

Чи 0допустимий пустий вихід ?
Тит

@Titus так.
Павло

Відповіді:



9

Python 3 , 38 байт

f=lambda x=0,*y:y>()and(x!=y[0])+f(*y)

Спробуйте в Інтернеті!


2
Так, знаю, ти можеш використовувати аргумент за замовчуванням, приємна знахідка.
xnor


@Dennis Як функція виходить з рекурсивного циклу, коли масив порожній? Я не бачу, як це не закінчується в maximum recursion depth exceeded.
Іоанна

@Ioannes Якщо залишився лише один елемент ( x ), він y>()буде оцінювати значення False , тому наступний код andне виконується.
Денніс

7

Haskell , 33 байти

f(a:b:r)=sum[1|a/=b]+f(b:r)
f _=0

Спробуйте в Інтернеті!


Бонус: Дещо цікаво безриментована арифметична версія (44 байти)

sum.(tail>>=zipWith((((0^).(0^).abs).).(-)))

Спробуйте в Інтернеті!

З огляду на вхід [1,1,4,3,3,3], ми спочатку беремо різницю суміжних записів ( [0,3,-1,0,0]), то absolute значення: [0,3,1,0,0]. Приймаючи нуль до потужності кожного елемента, перший раз поступається [1,0,0,1,1], а другий раз перевертає список: [0,1,1,0,0]( (1-)також буде працювати тут замість (0^)). Нарешті ми беремо sumсписок зі списку 2.



5

Мозок-Флак , 50 байт

([][()]){{}({}[({})]){{}<>({}())(<>)}{}([][()])}<>

Спробуйте в Інтернеті!

Виводить нічого за 0, що в мозковому спаді є рівнозначним. Якщо це не прийнятно, додайте це до +4байтів:({})

Пояснення:

#Push stack-height-1
([][()])

#While true:
{

    #Pop the stack-height-1 off
    {}

    #If 'a' is the element on top of the stack, and 'b' is the element underneath it, then
    #Pop 'a' off, and push (a - b)
    ({}[({})])

    #If (a-b) is not 0...
    {
        #Pop (a-b) off
        {}

        #Switch stacks
        <>

        #Increment the value on the other stack
        ({}())

        #Push a 0 back to the main stack
        (<>)

    #Endif
    }

    #Pop either (a-b) or the 0 we pushed
    {}

    #Push stack-height-1
    ([][()])

#Endwhile
}

#Toggle to the alternate stack and display the counter
<>


@Riley Чудово зроблено! :)
DJMcMayhem


1
@WheatWizard Я також спробував це, але він назавжди замикається на порожньому вході. -0+1 = 1
H.PWiz

5

Мозок-Флак , 50 байт

(([][()]){[{}]<({}[({})])>{(<{}>)()}{}([][()])}<>)

Спробуйте в Інтернеті!

# Get ready to push the answer
(

# Push stack height - 1
([][()])

# Loop until 0 (until the stack has a height of 1)
{

  # Pop the old stack height and subtract it 
  #(cancels the loop counter from the final answer)
  [{}]

  # Pop the top of the stack and subtract the next element from that
  # Don't include this in the final answer
  <({}[({})])>

  # If not 0
  {

    # Pop the difference between the last two numbers
    # Don't include this in the final answer
    (<{}>)

    # Add 1 to the final answer
    ()

  # End if
  }{}

  # Push stack height - 1
  ([][()])

# End while
}

# Switch to the off stack so we don't print anything extra
<>

# Push the total sum. This is the number of times the if was true
)

1
Поздравляємо за 10 кп!
Павло

@Pavel Дякую! Мені знадобилося назавжди отримати останні кілька сотень. Я занадто зайнятий іншими речами :(
Райлі

У мене було це
H.PWiz

@ H.PWiz У мене це було в один момент, але мені подобається, як поп скасовує натиск на висоту стека.
Райлі

5

Haskell , 35 байт

-8 байт завдяки H.PWiz.

Поле для гольфу за рекурсивною версією . Haskell є майже найкращим у рекурсії, і я пропустив це. > _ <

f l=sum[1|x<-zipWith(/=)l$tail l,x]

Спробуйте в Інтернеті!

Було б дивовижно, якби хтось придумав, як використовувати цю пораду .

Черговий розчин, 36 байт

f l=sum[1|True<-zipWith(/=)l$tail l]

Спробуйте в Інтернеті!



Ця порада пропускає вирішальний факт, який вам знадобиться, щоб uncurryфункція fпрацювала. Це sum.map fromEnum.(zipWith(/=)=<<tail), мабуть, найближче ви знайдете, але воно не працюватиме []і становить 37 байт ..
იმო

5

Java (OpenJDK 8) , 65 байт

Не такий короткий, як хотілося б, але це лише Java для вас.

Тестуйте, передаючи масив як список, розділений комами.

a->{int s=0,i=1;for(;i<a.length;s+=a[i-1]!=a[i++]?1:0);return s;}

Спробуйте в Інтернеті!


2
Якщо порожній масив не був тестовим випадком (а насправді я не вважаю його справді актуальним), можна було б використати: a->{int s=0,p=a[0];for(int n:a)s+=p==(p=n)?0:1;return s;}(57 байт).
Олів’є Грегоар

@ OlivierGrégoire Я знаю! Я написав це і подумав, що мені вдалося скоротити байти, але це не вдалося в першому випадку.
Люк Стівенс

3
56 байт:a->{int s=0;for(int i:a)s+=a[0]!=(a[0]=i)?1:0;return s;}
Невай



4

Мова Вольфрама (Mathematica) , 2324 26 29 байти

Length@Split@#~Max~1-1&

Спробуйте в Інтернеті!

  • -1 байт завдяки Мартіну Ендеру!
  • -2 байти завдяки JungHwan Min! приємне використання Split[].
  • -3 байти завдяки абсолютнолюдському!

невелике пояснення:

Splitподілить масив на список списків (з тих самих елементів), тобто перетвориться {1, 2, 2, 3, 1, 1}на {{1}, {2, 2}, {3}, {1, 1}}. Отже, Length@Split@#це кількість послідовних сегментів. Max[*****-1, 0]використовується для роботи з {}введенням даних.



1
24 байти:Max[Length@Split@#-1,0]&
JungHwan Min

23:Length@Split@#~Max~1-1&
Мартін Ендер


4

Символічний Python , 120 117 байт

Поле 3 байтів, видаливши явний перелік цілому числу (використовуючи унар +) для змінної лічильника - це означає, що якщо в масиві не буде змін, вихід буде Falseзамість 0, але це дозволено мета .

___=-~(_==_)
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___)
_=___

Спробуйте в Інтернеті!

# LINE 1: Generate value '2' for utility
___=-~(_==_)

# LINE 2: Get len(input) - 1
__('___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)')
   '___=~-'+`_>_`[___::___]+`__`[-~___]+'(_)'     # Generate string '___=~-len(_)'
            `_>_`[___::___]                       #    'le' spliced from 'False'
                           +`__`[-~___]           #    'n' indexed from '<function ...>'
   '___=~-'+                           +'(_)'     #    Remaining characters in plaintext
__(                                          )    # Execute this to get len(input) - 1

# LINE 3: Main calculation loop
__('__=___=_>_'+';___+=_[__]!=_[-~__];__=-~__'*___) 
__(                                               ) # Execute:
   '__=___=_>_'                                     #   Set var1, var2 to 0
               +';                           '*___  #   len(input) - 1 times do:
                       _[__]!=_[-~__]               #   Compare input[var1, var1 + 1]
                  ___+=              ;              #   Add this to var2
                                      __=-~__       #   Increment var1

# LINE 4: Set output variable ('_') to the result calculated.
_=___                                       

2
= _ = що це за майстерність?
повністюлюдсько


3

K (oK) , 8 байт

Рішення:

+/1_~~':

Спробуйте в Інтернеті!

Приклади:

+/1_~~':1 1 1 2 2 5 5 5 5 17 3
4
+/1_~~':()
0
+/1_~~':-3 3 3 -3 0
3

Пояснення:

Інтерпретується справа наліво:

+/1_~~': / the solution
     ~': / equal each-previous
    ~    / not (ie differ)
  1_     / 1 drop, remove first as this is different to null
+/       / sum up trues



3

R , 24 байти

cat(sum(!!diff(scan())))

Спробуйте в Інтернеті!

Те саме, що відповідь MATL, щойно використовується, sum(!!diff))оскільки немає nnz.


+1 Я думав, що використання rleбуде коротшим, але немає, length(rle()$v)використовує занадто багато символів і вимикається одним.
Ніл Фульц

@NealFultz це, мабуть, все-таки варто опублікувати як відповідь! Завжди добре бачити інший підхід. І ви повинні використовувати sum(rle()$v|1)замість цього length. :)
Джузеппе

3

Кубікс , 24 байти

UpO@0I>I!^-u>q.uvv$!^;)p

Спробуйте в Інтернеті

Зауважте, що Cubix використовує 0, щоб вказати, що більше немає входів, тому 0 не може бути у списку.

Пояснення

Розгорнуто:

    U p
    O @
0 I > I ! ^ - u
> q . u v v $ !
    ^ ;
    ) p

Ми починаємо з 0, натискаючи лічильник (ініціалізований з 0) і перший вхід ( I) на стек.

Потім вводимо цикл. При кожній ітерації циклу ми отримуємо наступний вхід з I. Якщо це 0, у нас не вистачає входів, тому ми повертаємо лічильник до вершини ( p), Output та exit ( @).

В іншому випадку ми беремо різницю двох перших елементів. Якщо це ненульове значення, ми обертаємо лічильник до верху, збільшуємо його і повертаємо назад до низу p)q. Потім ми з'являємо різницю; перш ніж переходити до наступної ітерації.

Усі символи, які тут не згадуються, - це лише керування потоком. Їх, як правило, багато в програмах Cubix.


@MickyT Хороший підхід, але ви, здається, перестараєтеся на 1. Ви можете поміняти на " 0a" (, але це не вдається на порожньому вході.

вибачте, перегляньте це ще раз
MickyT

3

Мозок-Флак , 50 байт

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

Спробуйте в Інтернеті!

Оскільки всі публікують свої 50-байтні рішення, це моє (у мене є 48-байтне) байтне, але це була проста модифікація DjMcMayhem, тому я вважав, що варто опублікувати)

Пояснення

У цій відповіді широко використовується скасування значення.

Без гольфу це схоже

([][()])({<{}({}[({})])>{<{}>()(<()>)}{}<([][()])>}<>)

Тут ми обчислюємо дельти до тих пір, поки у стеку не залишиться один елемент, кожного разу ми накопичуємо одне значення з внутрішньої петлі, якщо дельта не дорівнює нулю.

Це досить прямий спосіб зробити це.

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

([])({<{}>...<([])>}{})

те саме, що

(([]){[{}]...([])}{})

Коли значення модифікуються одним, те ж саме є. Це нам дає

(([][()]){[{}]<({}[({})])>{<{}>()(<()>)}{}([][()])}<>)

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

Ми можемо виконати ще одне зменшення, якщо ви побачите заяву

<(...)>{<{}> ...

ви можете насправді зменшити його

[(...)]{{} ...

Це працює, тому що якщо ми введемо цикл [(...)]і {}скасуємо, а якщо ми не зробимо значення, [(...)]було в першу чергу нульовим, і його не потрібно скасовувати. Оскільки у нас в коді є така модель, ми можемо її зменшити.

(([][()]){[{}][({}[({})])]{{}()(<()>)}{}([][()])}<>)

Це врятувало нас 2 байти, але також поставило два гнізда поруч. Їх можна комбінувати, щоб врятувати нас ще 2.

(([][()]){[{}({}[({})])]{{}()(<()>)}{}([][()])}<>)

І це наш код.



3

Гая , 2 байти

ėl

Спробуйте в Інтернеті!

Це зловживає помилкою (або особливістю?) Gaia, що кодування довжини виконання не враховує останній запуск елементів. Зауважте, що я перевірив двічі, він працює для всіх тестових випадків.

  • ė - Запустити кодування довжини (із недоліком, описаним вище).
  • l - Довжина.

2

JavaScript (ES6), 35 байт

a=>a.filter((e,i)=>e-a[i+1]).length

Цікаво, чи можна це скоротити за допомогою рекурсії. Але моя найкраща спроба також 35:f=([a,...b])=>1/a?!!(a-b[0])+f(b):0
Арнольд

@Arnauld Я також спробував це, але зробив неправильний облік і подумав, що це 36 байт, інакше я би додав це як альтернативу.
Ніл





2

Рубін , 31 байт

->a{a.chunk{|x|x}.drop(1).size}

Спробуйте в Інтернеті!


Замість цього .drop(1)ви можете зробити[1..-1]
Cyoce

@Cyoce На жаль, dropповертає перелік, а не масив, так що це не працює.
Йорданія

так. Він повертає масив у моїй версії.
Cyoce

@Cyoce Яка версія?
Йорданія

Я на 1.9.3, але чому ви не можете взяти sizeмасив?
Кіос

2

C (gcc 5.4.0), 61 байт

f(c,v)int*v;{int*p=v,s=0;for(;p<v+c-1;s+=*p++!=*p);return s;}

Спробуйте в Інтернеті!

f - це функція, що приймає довжину масиву та вказівник на перший елемент масиву і повертає кількість змін у масиві;

У цьому поданні використовується невизначена поведінка ( *p++!=*p, p використовується двічі в виразі, в якому вона змінюється), яка працює на моїй машині (gcc 5.4.0) та TIO, але може не працювати в інших реалізаціях або версіях.

Пояснення:

f(c,v)int*v;{ // old-style declaration for v, and implicit-int for c and return value
    int*p=v,s=0; // p is a pointer to the current item, s is the number of changes
    for(;p<v+c-1;s+=*p++!=*p); // for each consecutive pair of integers, if they are different, add one to the number of changes
    return s; // return the number of changes
}

Не могли б ви додати посилання на середовище тестування в Інтернеті?
Джонатан Фрех

@JonathanFrech Додано
pizzapants184

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.