Повністю-паліндромні трикутники


18

Розглянемо рядок 160615051. Його можна "трикутнити" як таке:

  1
 606
15051

Тоді кожен ряд - паліндром. Також зверніть увагу, що кожна сторона по периметру також є паліндром:

  1  |   1   |   
 6   |    6  |      
1    |     1 | 15051 

Тому цей рядок можна вважати повністю паліндромним трикутником. Не турбуйтеся про висоту 100в цьому випадку, вона не повинна бути паліндромною.

Введення: Рядок символів для друку ASCII від 0x20 до 0x7E. Це може бути масив символів, одна рядок або масив кодових точок ASCII. Ваш вклад завжди зможе бути трикутним (тобто його довжина завжди буде ідеальним квадратом).

Вихідні дані : значення "truthy", якщо рядок є повністю паліндромним трикутником, або значення фальси в іншому випадку.

Тестові справи

input => output

1 => true
A => true
AAAA => true
nope => false
{{}} => false
1101 => true
1011 => false
1202 => false
111110001 => true
160615051 => true
160625052 => false
1111111111111111 => true
1121123211234321123454321 => true
HHeHHeleHHellleHHellolleH => true
HellolleHHellleHHeleHHeHH => false
111111111111111111111111111111111111 => true
abcbdefeddefgfedbcdefedcbabcdefedcba => true

Відповіді:


10

Желе , 14 12 байт

J’ƲœṗZ⁻¦µU⁼

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

Фон

Почнемо з ознайомлення з 0-індексами вхідного рядка.

 H  H  e  H  H  e  l  e  H  H  e  l  l  l  e  H  H  e  l  l  o  l  l  e  H
 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

Щоб отримати рядки трикутника, ми можемо розділити рядок перед показниками 1 , 1 + 3 = 4 , 1 + 3 + 5 = 9 і 1 + 3 + 5 + 7 = 16 . Оскільки (n + 1) ² = n² + (2n + 1) , ці суми є саме позитивними, ідеальними квадратами у списку індексів. Якщо ми також розділимо рядок перед 0 , це так само просто, як розділення перед усіма індексами на основі 0, які є ідеальними квадратами.

Після розщеплення отримуємо наступні рядки.

""
"H"
"HeH"
"HeleH"
"HellleH"
"HellolleH"

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

"HHHHH"
"H"
"HeH"
"HeleH"
"HellleH"
"HellolleH"

Тепер завдання зводиться до перевірки того, чи повернення всіх рядків дає один і той же рядковий масив.

Як це працює

Спочатку Jгенерується всі 1-базисні індекси вхідного рядка J, потім зменшується їх, щоб отримати всі 0-базисні індекси. Ʋперевіряє всі 0-основні індекси на квадратність. У нашому прикладі зверху це дає наступний булівський масив.

 1  1  0  0  1  0  0  0  0  1  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0

Далі ми закликаємо œṗрозділити рядок введення, наприклад,

 H  H  e  H  H  e  l  e  H  H  e  l  l  l  e  H  H  e  l  l  o  l  l  e  H

раніше всіх 1 -х (насправді, всі елементари). У нашому прикладі це дає наступний масив рядків.

['', 
 'H',
 'HeH',
 'HeleH',
 'HellleH',
 'HellolleH'
]

Z⁻¦це, мабуть, найцікавіша частина цієї відповіді. Давайте Z1¦спочатку проаналізуємо більш прямолінійну .

¦є рідким швидким. Він споживає два посилання зі стека, конкретно 1і Zв цьому випадку. Спочатку Zзастосовується до його аргументу: рядковий рядок від раніше. Zє атомом zip та зчитує масив рядків / 2D-масив символів за стовпцями, поступаючись

['HHHHH',
 'eeee',
 'Hlll',
 'ell',
 'Hlo',
 'el',
 'Hl',
 'e',
 'H'
]

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

Тепер ¦заглядає 1і знаходить єдиний індекс: 1 . Таким чином, перша рядок у вихідному масиві рядків замінюється першою рядком у зворотному значенні Z; рядки інших індексів залишаються без змін.

['HHHHH',
 'H',
 'HeH',
 'HeleH',
 'HellleH',
 'HellolleH'
]

Давайте назвемо цей масив .

Ми використовували Z⁻¦замість Z1¦, але це не має ніякої різниці: порівнює масив рядків із вхідним рядком для нерівності, отримуючи 1, оскільки вони не рівні. Різниця між ними полягає в тому, що Z⁻¦це діадіальність, оскільки це дозволяє нам писати œṗZ⁻¦замість œṗ¹Z1¦. Це пояснюється тим, що dyad ( œṗ), за яким слідує monad ( œṗ¹Z1¦), - це вилка (монада застосовується до аргументу ланцюга / вхідного рядка, а повернене значення передається як правильний аргумент œṗ), тоді як діада, за якою слідує інша діада (або в кінці ланцюга) - гачок , тобто його правильним аргументом є аргумент ланцюга.

Залишилося лише перевірити паліндромність. µпочинається нова (одномісний) ланцюгом Хто є аргумент . Вгору ноги атом змінює все рядки в A (але не сам), а потім порівнює результат з А для рівності. Повернений булевий 1 вказує на повністю паліндромний трикутник; інші рядки повернуть 0 .U


Я дійсно повинен навчитися читати желе. (Пояснення, будь ласка?)
CAD97

1
Я відредагував свою відповідь.
Денніс

6

Japt , 25 21 17 байт

Збережено 2 байти завдяки @obarakon

ò@°T ¬v1
pUmg)eêP

Перевірте це в Інтернеті!

Як це працює

 ò@  ° T ¬ v1   // Implicit: U = input string, T = 0
UòXY{++T q v1}  // First line; reset U to the result of this line.
UòXY{        }  // Partition U at indices where
     ++T q      //   the square root of T incremented
           v1   //   is divisible by 1.
                // This breaks U at square indices, giving rows of 1, 3, 5, ... chars.
 pUmg)eêP
UpUmg)eêP
  Umg           // Take the first char of every item of U.
Up   )          // Append this to U.
      e         // Check that every item in the resulting array
       êP       // is a palindrome.
                // Implicit: output result of last expression

Зауважте, що нам не потрібно перевіряти обидві сторони; якщо сторони не однакові, принаймні один з рядів не є паліндром.


Це ця багаторядкова річ нова особливість Japt?
Лука

@Luke Так, я щойно додав це у вівторок. Це мій перший шанс показати це :-)
ETHproductions

Не зважайте на мою підказку з гольфу. Це просто перевірити, чи був кожен рядок паліндромним, що також дало правильні результати ...
Лука


4

Желе , 18 16 байт

J²‘Ṭœṗ⁸ZḢ$ṭ$ŒḂ€Ạ

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

Завдяки Джонатану Аллану за тривіальну, але не настільки очевидну економію -2 байт.


Використовуйте мою конструкцію трикутника і збережіть байт:JƲ0;œṗ⁸ZḢ$ṭ$ŒḂ€Ạ
Джонатан Аллан

... насправді поєднайте цю ідею з неправдою і збережіть ще один байт, оскільки розділення буде "заштриховано найкоротше":J²‘Ṭœṗ⁸ZḢ$ṭ$ŒḂ€Ạ
Джонатан Аллан

@JonathanAllan Umm ... навіщо мені це взагалі потрібно ½? Тепер Jмає більше сенсу ...
Ерік Аутгольфер

3

JavaScript (ES6), 112 байт

f=(s,n=1,t='',u='',g=([...a])=>''+a==a.reverse())=>s?g(s.slice(0,n))&f(s.slice(n),n+2,t+s[0],u+s[n-1]):g(t)&g(u)

tі uзібрати боки, щоб їх можна було перевірити в кінці.


2

C #, 184 байти

using System.Linq;
b=a=>string.Concat(a.Reverse())==a
f=>{string c=f[0]+"",d=c,e="";for(int i=1,k=1,s=f.Length;i<s;)
{c+=f[i];d+=f[(i+=k+=2)-1];e=f.Substring(s-k);}return b(c)&b(d)&b(e);}

Думав, що рішення виглядає добре, поки я не дістався до частини паліндром

Негольована версія:

Func<string, bool> b = a => string.Concat(a.Reverse()) == a;
        Func<string, bool> func = f => {

            string c = f[0] + "", d = c, e = "";

            for (int i = 1, k = 1, s = f.Length; i < s;) {
                c += f[i];
                d += f[(i += k += 2) - 1];
                e = f.Substring(s - k);
            }

            return b(c) & b(d) & b(e);
        };

Чи можете ви перейти e=..до рядка for для збереження байта? Не потрібно зараховувати нові рядки до числа байтів, тому я припускаю, що ви цього не зробите.
TheLethalCoder

Ні, я не рахую нові рядки, я не можу перемістити e в цикл, тому що мені це потрібно в операторі return.
LiefdeWen

Я мав на увазі так....; i < s;e = f.Substring(s - k)){c+=....
TheLethalCoder

2

Java 8, 358 301 байт

import java.util.*;s->{List<String>l=new Stack();for(int i=0,p=1,t=1;p<=s.length();p+=t+=2)l.add(s.substring(i,i=p));String a="",b=a;for(String q:l){a+=q.charAt(0);b+=q.charAt(q.length()-1);}return p(a)&p(b)&p(l.get(l.size()-1));}boolean p(String s){return s.equals(new StringBuffer(s).reverse()+"");}

Вхід - a String, вихід - a boolean.

Пояснення:

Спробуйте тут.

import java.util.*;               // Required import for List and Stack

s->{                              // Method (1) with String parameter and boolean return-type
  List<String>l=new Stack();      //  Create a String-list
  for(int i=0,p=1,t=1;            //  Initialize some index/counter integers
      p<=s.length();              //  Loop (1) over the String in sections
      p+=t+=2)                    //    And increase `p` like this after every iteration: 1,4,9,16,25,etc.
    l.add(s.substring(i,i=p));    //   And add a substring-section to the list (0,1 -> 1,4 -> 4,9 -> 9,16 -> etc.)
                                  //  End of loop (1) (implicit / single-line body)
  String a="",b=a;                //  Two temp Strings
  for(String q:l){                //  Loop (2) over the list
    a+=q.charAt(0);               //   And append the first character to String `a`
    b+=q.charAt(q.length()-1);    //   And the last character to String `b`
  }                               //  End of loop (2)
  return p(a)                     //  Return if String `a` is a palindrome
        &p(b)                     //   as well as String `b`
        &p(l.get(l.size()-1));    //   as well as the last String in the list
}                                 // End of method (1)

boolean p(String s){              // Method (2) with String parameter and boolean return-type
  return s.equals(new StringBuffer(s).reverse()+"");
                                  //  Return if this String is a palindrome
}                                 // End of method (2)

1

Желе ,  20  21 байт

+2 байти - я випустив баггі-код :(
-1 байт - перейшов від ліплення як непарних цілих чисел до поділу на квадратні індекси

JƲ0;œṗ⁸ZḢ$ṭ$ŒḂ€Ạ

Монадійне посилання, що приймає список символів і повертається 1(Truthy) або 0(Falsey).
Примітка: тут використовується частина специфікації, яка обмежує вхід до квадратної довжини.

Спробуйте в Інтернеті! або побачити тестовий набір .

Це може бути спрощено до 17 байтів , зазначивши, що якщо всі рядки є паліндромами, лише одна "сторона" потребує перевірки ( JƲ0;œṗ⁸ZḢ$ṭ$ŒḂ€Ạ), однак Ерік Аутгольфер вже помітив цей факт і використав його у своїй відповіді, тому я дав метод побудови трикутника для їх збереження байт там.

Крім того, це, в свою чергу, може бути покращено до 16 байт , зазначивши, що розділення на truthy індекси не проти, якщо в лівому аргументі є надлишок ( J²‘Ṭœṗ⁸ZḢ$ṭ$ŒḂ€Ạ).

Як?

JƲ0;œṗµ2BịЀ⁸Z;⁸ŒḂ€Ạ - Link: list, a      e.g. "abcbazxza"
J                     - range of length of a  = [1,2,3,4,5,6,7,8,9]
 Ʋ                   - is square? (vectorises) [1,0,0,1,0,0,0,0,1]
   0;                 - prepend a zero        [0,1,0,0,1,0,0,0,0,1]
     œṗ               - partition a at 1s     ["a","bcb","azxza"]
       µ              - monadic chain separation, call that t
        2B            - 2 in binary = [1,0]
             ⁸        - chain's left argument, t
          ịЀ         - map with index into    ["aa","bb","aa"] (1st and last of each of t)
              Z       - transpose              ["aba","aba"] (left and right "sides" of t)
               ;⁸     - concatenate t          ["aba","aba","a","bcb","azxza"]
                 ŒḂ€  - palindromic? for €ach  [1,1,1,1,1]
                    Ạ - all?                   1

1
Дарн, я ось-ось збирався зробити відповідь Желе. Хоча технічно моє помиляється і подобається вдвічі довше ... приємна робота :): P
HyperNeutrino

"зауваживши, що розділення на truthy індекси не проти, якщо є лівий аргумент", також помічено перед читанням.
Ерік Аутгольфер

1

Математика, 156 байт

B=StringTake;Count[PalindromeQ/@Join[A=Table[B[#,{i^2+1,(i+1)^2}],{i,0,(s=Sqrt@StringLength@#)-1}],{StringJoin@Table[B[A[[i]],1],{i,Length@A}]}],True]==s+1&


вхід

["1101"]


Ви не можете замінити If[<stuff>, True, False]просто <stuff>? Я думаю, що And@@(...)він коротший Count[...,True]==s, а це також означає, що вам не потрібно визначати sяк змінну.
Не дерево

Зачекайте, це насправді перевіряє діагоналі? Я отримую помилкові позитиви для пари тестів ( "1202"і "160625052").
Не дерево

всі проблеми виправлені
J42161217


1

Java, 136 байт

l->{for(int i=0,j,k=1;i<l.size();i=j,k+=2)if(!l.subList(i,j=i+k).equals(l.subList(i,j).asReversed().toList()))return false;return true;}

Використовує a MutableList<Character>з колекцій Eclipse

Function<MutableList<Character>, Boolean> func = l->{
   for(int i=0,j,k=1;i<l.size();i=j,k+=2)  // `i` is the start index, `j` is the end index, `k` increments by 2
       if(!l.subList(i,j=i+k).equals( //Check that the first partition equals
           l.subList(i,j).asReversed().toList())  // The same sublist reversed
       )
       return false;
   return true;
};


0

Excel VBA, 87 байт

Анонімна функція негайного вікна VBE, яка приймає вхід з комірки [A1]та виводить у безпосереднє вікно VBE

k=1:For i=1To[Len(A1)^.5]:s=Mid([A1],j+1,i*2-1):j=j+i*2-1:k=k*(s=StrReverse(s)):Next:?k

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