[C#] Домашно Strings and Text Processing - 23 задача


4

Условие: Write a program that reads a string from the console and replaces all series of consecutive identical letters with a single one. Example: "aaaaabbbbbcdddeeeedssaa" -> "abcdedsa".

Решениеsource.

Обяснение: Отново с регулярен израз става по-лесно, като тук взимаме последния проверен символ.




Отговори



0
Здравей, ако искаме всеки символ да се повтаря два пъти, знаеш ли тогава какъв е изразът?Когато сменя едно с две не се получава.
@"(\w)\2+", "$1"

от lubolub1 (209 точки)


0
Console.WriteLine(Regex.Replace(str, @"(\w)\1+", "$1$1"));

от jasssonpet (6814 точки)

0
В регулярният израз \1 не е брой повторения, а замества символа, присвоен на \w. Изразът се чете "Намери символ (\w) последван от същия символ (\1) един или повече пъти (+)". Ако искаш да ги намира по двойки, махни плюса: (\w)\1 или (\w)\1{1} Ако търсиш по тройки: (\w)\1{2}

от AntonPetrov (654 точки)


0
Варианта без регулярен израз /с няколко реде естествено е по дълъг:)/ е StringBuilder и цикъл, който изтрива текущия символ, ако е еднакъв с предишния. Ако искаш символите да се повтарят до определен брой пъти, проверяваш съответния символ назад в редицата.

от slavii (0 точки)


0
Ето и кода без регулярен израз със StringBuilder. https://github.com/tsvetomir-nikolov/TelerikAcademy/blob/master/C%23%20part%202/Strings%20and%20text%20processing/ReplaceConsecutiveLetters/Program.cs



3

http://pastebin.com/Lq6A8ji6

Подобно решение на това на колегата отгоре, само , че малко по- различна имплементация, не довабям в StringBuildera, а махам съоветно елементите, които се повтарят, има малко игра с границите на масива и кой елемент точно да махаме, но като цяло е простичко.


от boncho.vylkov (1923 точки)


3

Решение 1.0 ver.

http://pastebin.com/mUdEnmNy

Обяснение 1.0 ver.

Това беше първият ми вариянт. Като задачата си я представих че от текст сплитвам всички думи по познатият ни начин. След което набутвам всички думи в лист и ходя по думите и буквите. Ако следващата буква е еднаква с текущата изтривам текукащата и задържам брояча / i--; / същевременно намалявам индекса в който for цикъла трябва да спре, все пак един елемент е изчезнал и ако не го намаля ще излезе от границите ;)

Интересно: Не ги правя с StringBuilder-a , за статистика замерих 2та вариянта за една дълга дума как ще се справят. StringBuilder-а е 4-5 пъти по бърз.

Решение 2.0 ver.

http://pastebin.com/5CsNkZ7y

Обяснение 2.0 ver.

Тук имам един string. Като започвам да проверявам всеки substring с следващия с for цикъл и така до str.Length - 1. Като пак важно е да се обърне внимание на момента когато премахвам някой substring, тогава "задържам" брояча , като използвам i -- ; всеки път след като имам изтриване.

В общи линии това е.

 


от Assi.NET (3050 точки)


0
как ти е името в системата, че като ме питат накрая кой ми е помогнал да те пиша заедно с jasssonpet? :)

от nevtod (1087 точки)

0
Assi.NET както тук в форума и БГ КОДЕРА Радвам се че съм ти помогнал по някакъв начин :)

от Assi.NET (3050 точки)



0

Решение

сравнявам всеки следващ с предходния - ако е различен от него добавям предходния. Естествено ако последния е символ го има само 1 път няма да се добави тъй като i ще излезе извън границите за това има и една допълнителна проверка накрая, за да не бъде пропуснат.


от Rokata (397 точки)


1

Едно решение и от мен без регулярни изрази. За разлика от другите колеги, аз съм приел, че само повтарящи се букви (латински) не се принтират, ако има повтарящи символи се принтират всички. Постарал съм се имената на променливите да са лесно разбираеми, дано се е получило :)

http://pastebin.com/yeDDQ0c3




0
супер, много готина подсказка, само че преди да ти прочета решението си преправих кода ето така if (input[i] != input[i - 1] && char.IsLetter(input[i])) replaced.Append(input[i]); else { if(!char.IsLetter(input[i])) replaced.Append(input[i]); } работи и за други азбуки, иначе така си ограничаваш входа само до латинските!

от pdrenovska (2196 точки)

0
е досега не знаех, че има char.IsLetter....та благодаря :)



0

+1  без регулярен израз. Проверявам дали съседните букви са еднакви, ако да - ги записвам в каунт, междувременно тече и друг каунт. В момента в който буквите станат различни, едини каунтър става по-голям от другия и записвам в СтрингБилдъра първата буква, а каунтарите стават = 0 и така до края...Това е което ми дойде първо на ум, само накрая не ми излиза поснедната буква от стринга и си я добавям по друг начин :D.

http://pastebin.com/qNPp0Hen




0

Според мен коректният регулярен израз би трябвало да е 

string regex = @"(?<letter>[A-Z])\1+";

тъй като търсим "letters", а "\w" включва цифри и символът долна черта. Разбира се нужно е да се ползва RegexOptions.IgnoreCase , защото в израза проверяваме само главни букви.


от Anubis_Black (1521 точки)


0

Здравейте,

Споделям и своето решение тук

Използвах регулярен израз от вида "([a-z]{1})\1+"

Поздрави.




0

Ето и от мен едно решение зверски просто и се получи доста добре според мен.  Като цяло това което прави е, че когато вземе първата буква в bool масив слага true на поредния номер от азбуката на съответната буква и проверява дали следващата не е същата, когато е различна изчиства true на предната буква и слага за поредната и така... - SOURCE.


от IceElementor (398 точки)


0
Хитра идея. Ако правилно съм разбрал, в булевия масив винаги има най-много един елемент true, тоест излишно пазиш 26 позиции. Можеш просто да пазиш една чар променлива newSymbolFound, на която присвояваш currentLetter, ако са различни. Съвет - вместо (int)currentLetter - 65 по-добре е да ползваш направо currentLetter - 'A'. По-ясно е какво се крие зад 65. От условието на става ясно , но според мен така ще замениш некоректно "aaaAAaaa" с "a", вместо с "aAa". Поздрави.

от AntonPetrov (654 точки)

0
Да, прав си по-добре ще е да пазя само едната буква, а и да от условието не се разбира дали може и главни букви.

от IceElementor (398 точки)