Знайдіть стежки!


10

Ви повинні написати програму або функцію.

Вхід - «карта» чисел. Ви можете вибрати карту як рядок з новими символами рядків ( \n) або 2D масивом рядків.

Усі карти містять 5 символів на 5 символів, і символи завжди є або цифрами, більшими за 0, або пробілами.

Ось приклад карти:

12 45
11233
  233
    1
2 899

Ваше завдання - знайти підключені компоненти на карті. Дійсний компонент - це принаймні три горизонтально та / або вертикально ( не діагонально ) з'єднані однакові цифри ( не пробіли ). Потім вам потрібно буде замінити символи дійсних підключених компонентів на xs та надрукувати або повернути цей результат.

Отже, вихід для наведеного вище прикладу буде:

x2 45
xx2xx
  2xx
    1
2 899

Ось ще один тестовий випадок (завдяки Мартіну Ендеру):

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

Це код гольфу, тому найкоротший код у байтах виграє!



Чи дозволені вбудовані модулі?
Іоанна

@Joannes, так.
Даніель

Відповіді:


1

JavaScript (ES6), 171 161 139 137 136 133 132 байт

f=(a,i=0)=>(F=i=>" "<c&&a[i]===c&&(a[i]=n,1+F(i-1)+F(i+1)+F(i-6)+F(i+6)),n=1,c=a[i],n=F(i)>2?"x":c,c=1,F(i),i>28?a:f(a,++i+(i%6>4)))
<!-- this HTML included just for testing --><textarea rows=5 cols=6 oninput="document.querySelector`pre`.innerHTML=this.value.length==29?f([...this.value]).join``:'invalid input'">12 45&#10;11233&#10;  233&#10;    1&#10;2 899</textarea><br/><pre></pre>

Це переклад моєї відповіді Python. I / O як символьні масиви.

Шкода, що немає ефективного способу зробити sum...


5

Пітон 3, 238 237 200 199 192 181 байт

def f(a,i=0):F=lambda i,n,c:29>i>=0!=" "!=a[i]==c!=n and(a.__setitem__(i,n)or-~sum(F(i+j,n,c)for j in[-1,1,-6,6]));j=i+i//5;F(j,[a[j],"x"][2<F(j,1,a[j])],1);i>23or f(a,i+1);return a

Визначає функцію, f(a)яка приймає вхід як масив символів і повертає той самий модифікований масив. ( За замовчуванням масиви символів прийнятні як рядки. )

Нероздягнений з поясненнями

Змінений код є рекурсивним, але працює однаково.

# The main function; fills all continuous nonempty areas of size >= 3 in array
# with x's. Both modifies and returns array.
def findpaths(array):
    # Fills a continuous area of curr_char in array with new_char, starting
    # from index. Returns the number of cells affected.
    def floodfill(index, new_char, curr_char):
        if (0 <= index < 29                   # Check that the position is in bounds
                and (index + 1) % 6 != 0      # Don't fill newlines
                and array[index] != " "       # Don't fill empty cells
                and array[index] == curr_char # Don't fill over other characters
                and curr_char != new_char):   # Don't fill already filled-in cells
            array[index] = new_char # Fill current position
            return (1 # Add neighboring cells' results, plus 1 for this cell
                    + floodfill(index + 1, new_char, curr_char)  # Next char
                    + floodfill(index - 1, new_char, curr_char)  # Previous char
                    + floodfill(index + 6, new_char, curr_char)  # Next line
                    + floodfill(index - 6, new_char, curr_char)) # Previous line
        return 0 # Nothing was filled. The golfed solution returns False here,
                 # but that's coerced to 0 when adding.

    for i in range(25): # Loop through the 25 cells
        i += i // 5 # Accommodate for newlines in input
        curr_char = array[i] # Get the cell's contents
        # Fill the area from the cell with dummies
        area_size = floodfill(i, 1, curr_char)
        # Convert dummies to "x" if area was large enough, back to original otherwise
        fill_char = "x" if 2 < area_size else curr_char
        floodfill(i, fill_char, 1)
    return array

2 байти, щоб перемогти рішення математики ...
FlipTack

1
@FlipTack Так. Я не думаю, що це відбувається сьогодні, але я перекладаю це на JS, і це виглядає перспективно.
PurkkaKoodari

3

Рубін, 304 байти

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end
def b2(s,i,c)
  if(0...s.size)===i&&s[i]==c&&!@v[i]
    @v[i]=s[i]='x'
    [1,-1,6,-6].each{|j|b2(s,i+j,c)}
  end
  s
end
def f(s)
  z = s.dup
  ps = ->(i){b(z.dup,i).scan('x').size}
  (0...s.size).each{|i|b(s, i)if ![' ',"\n"].include?(s[i])&&ps.call(i)>2}
  s
end

Приклад використання:

puts f(File.read("map.txt"))

код повторно використовує метод 'blot' для обчислення довжини шляху.

змінні / методи:

  • f (s): функція для перетворення рядка карти, повертає нову карту з 'x's
  • ps (i): розмір шляху від індексу карти i (де x = i% 6, y = i / 6)
  • s: рядок введення, рядки карти, розділені "\ n"
  • z: копія рядка введення
  • b (s, i): функція 'blot': записує 'x' з індексу карти i над шляхами
  • @v: масив "відвідав"

Спроба більш детального пояснення:

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

z = s.dup

визначити анонімну функцію 'ps' (довжина шляху) (лямбда), яка приймає індекс i як аргумент. він повертає довжину шляху з цієї точки. це робиться за допомогою виклику методу 'b' (блот), щоб вставити x на копію оригінальної карти, а потім підрахувати кількість x у повернутому рядку.

  ps = ->(i){b(z.dup,i).scan('x').size}

наступна частина повторює кожен символ на карті (індекс i, символ s [i]). він викликає функцію 'b' (блот) у положенні i на карті, якщо довжина шляху від позиції i більше 2, і якщо це не символ пробілу чи нової лінії.

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

функція b (блот) бере аргумент рядка карти та індексу. він ініціалізує @v (відвіданий масив) і викликає функцію помічника b2.

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

функція b2 приймає рядок карти, положення карти (i) та символ у поточному шляху (c). він закликає себе рекурсивно замінювати підключені ділянки цифр символом 'x'. він повертає вхідний рядок (це так, що функція ps може викликати scan () на зворотному значенні).

це якщо оператор перевіряє, чи вказане положення карти (i) знаходиться в межах рядка (0 ... s.size) і що символ у s [i] є таким же, як початковий символ. також перевіряється @v [i], щоб уникнути нескінченної рекурсії.

if(0...s.size) === i && s[i] == c && !@v[i]

це біт, який замінює символ у індексі (i) символом 'x'. він також позначає цей індекс як відвіданий.

@v[i] = s[i] = 'x'

саме тут b2 викликає себе рекурсивно, шукаючи шлях. i + 1 - один символ праворуч, i-1 - один символ зліва, i + 6 - один рядок вниз (5 цифр + 1 новий рядок = 6 символів), i-6 - один рядок вгору.

[1,-1,6,-6].each { |j| b2(s, i+j, c) }

1

C (Ansi), 243 233 179 188 байт

Гольф:

#define O o[1][l]
x,n,l,L;r(o,l)char**o;{if(!(l>L|l<0|O<47|O!=x))n++,O++,r(o,l-1),r(o,l+6),r(o,l-6),r(o,l+1),n>2?O='x':O--;}main(g,o)char**o;{for(;(L=30)>l;l++)n=0,x=O,r(o,l);puts(o[1]);}

З анотаціями:

#define O o[1][l]
x,n,l,L;      /*-------------------------- Globals*/
r(o,l)char**o;{ /*------------------------ Recursive Function*/
    if(!(l>L|l<0|O<47|O!=x)) /*----------- if this cell is valid(in
                                              range, is a number, is the 
                                              same as the parent number*/
    n++,     /*--------------------------- Increment count*/
    O++,     /*--------------------------- Increment character to mark*/
    r(o,l-1),  /*------------------------- Recurse left*/
    r(o,l+6),  /*------------------------- Recurse down*/
    r(o,l-6),  /*------------------------- Recurse down*/
    r(o,l+1),  /*------------------------- Recurse right*/
    n>2?O='x':O--;  /*---------------------If greater than 3, replace with x, else decrement character*/ 
}          /*----------------------------- Return*/

main(g,o)char**o;{ /*--------------------- Main*/
    for(;l<(L=30);l++){ /*---------------- For entire string and set L*/
        n=0;
        x=O;        /*-------------------- set counter to 0*/
        r(o,l); /*------------------------ Recurse*/
    } /*---------------------------------- End While*/
    puts(o[1]); /*------------------------ Print*/

}

Вхід:

Очікує новий рядок на початку та в кінці рядка.

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

./findPaths "
12 45
11233
  233
    1
2 899
"

Приклад Вихід:

x2 45
xx2xx
  2xx
    1
2 899

Оновлення

Виправлення сітки дозволило мені поголити майже 60 байт.


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

1

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

(f=Flatten@#;p=Partition)[If[Tr[1^VertexComponent[r~Graph~Cases[##&@@p[#,2,1]&/@Join[g=p[r,5],g],{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b],#]]<3,f[[#]],"x"]&/@(r=Range@25),5]&

Пояснення:

(f=Flatten@#;p=Partition)[
  If[
    Tr[1^VertexComponent[
        r~Graph~Cases[
          ##&@@p[#,2,1]&/@Join[g=p[r,5],g],
          {a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b
        ],
        #
      ]]<3,
    f[[#]],
    "x"
  ]&/@(r=Range@25),
  5
]&

Чиста функція, яка приймає 5x5масив. є 3-байтним символом приватного користування, що U+F3C7представляє оператор транспонування постфікса \[Transpose].

(f=Flatten@#;p=Partition): Згладжує список вводу та зберігає його f. Встановлює p = Partitionта повертає.

g=p[r,5]: Масив {{1,2,3,4,5}, ..., {21,22,23,24,25}}(це тому, що rвстановлюється Range@25).

Join[g=p[r,5],g]: список рядків і стовпців g.

p[#,2,1]&: Чиста функція, яка розділяє список #на підлістики довжини 2з перекриттям 1; тобто список сусідніх пар в #.

##&@@p[#,2,1]&: Те саме, що вище, за винятком того, що він повертає a Sequence.

##&@@p[#,2,1]&/@Join[g=p[r,5],g]: Картує попередню функцію рядків і стовпців, gщоб отримати список усіх сусідніх записів у g. Моя кишка каже, що існує коротший спосіб зробити це.

r~Graph~Cases[...]: Графік, вершини якого є цілими числами 1, ..., 25та ребрами яких є краї між сусідніми записами, у gяких є однакові відповідні записи у вхідному масиві (крім " ")

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": Шаблон, який відповідає {a,b}такому, що f[[a]] == f[[b]](те саме значення у вхідному масиві) і якому не дорівнює " ". Встановити A = f[[a]]для збереження 1байт.

...:>a<->b: Замініть кожну відповідність непрямим краєм від a до b.

VertexComponent: Повертає зв'язаний компонент другого аргументу (вершину) у першому аргументі (графік).

Tr[1^VertexComponent[...]]: Розмір підключеного компонента. Збереже 1байт від Length@VertexComponent[...].

If[Tr[...]<3,f[[#]],"x"]&: Чистий функція , яка приймає запис #в g. Якщо розмір його підключеного компонента менший 3, замініть його відповідним записом на вході. В іншому випадку замініть його на "x".

(f=Flatten@#;p=Partition)[...,5]: І, нарешті, переформатуйте результат на 5x5масив.


0

Clojure, 188 байт

Це досить непосильне: D

#(apply str(map-indexed(fn[i v](if((set(flatten(for[m(range 30)](let[n(for[p[-1 -6 1 6]:when(=(get %(+ m p)0)((set"123456789")(% m)))](+ m p))](if(< 1(count n))(conj n m)[])))))i)\x v))%))

Називається так (потрібен 1D вектор символів):

(def f #(apply str(...))

(print (str "\n" (f (vec (str "12 45\n"
                              "11233\n"
                              "  233\n"
                              "    1\n"
                              "2 899\n")))))

(print (str "\n" (f (vec (str "2   3\n"
                              "    4\n"
                              " 1  5\n"
                              "111 6\n"
                              "11  7\n")))))

Занадто ліниво, щоб зняти гольф, але в основному for[m(range 30)]відвідує кожен індекс, а для кожного індексу внутрішній let[n(for[p[-1 -6 1 6]...(+ m p))]складає список від 0 до 4 елементів, у якому перераховані місця, які мали те саме значення (1 - 9), як середнє місце. Якщо більше одного сусіда відповідає середній частині, це означає, що всі вони утворюють кластер, тому ці місця додаються до набору, який використовується у (if((set(flatten(...)))i). Якщо iз набору знайдено індекс, то \xвиводиться вихідне значення, а вихідне значення - інакше. Це :when( ... )досить цікаво ...

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