Skracanie wyrazów od wybranego znaku

0

Witam,
Ma za zadanie napisać program, który skraca wyraz od wybranego znaku, czyli, np. podaję ilość testów, potem aaaaaa, następnie 3 to program powinien pokazać a4. Jednak mój program na wyjściu pokazuje jakieś bzdury. Nie mogę gdzie w kodzie jest błąd.

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>

using namespace std;

string konwersjaIntNaString (int liczba)
{
    ostringstream ss;
    ss << liczba;
    string str = ss.str();

    return str;
}

int obliczWystapieniaWybranegoZnaku (string wyraz, int pozycjaZnaku)
{
    int iloscWystapien = 1;
    if (wyraz.length() > pozycjaZnaku)
    {
        while (wyraz[pozycjaZnaku] == wyraz[pozycjaZnaku + 1])
        {
            iloscWystapien++;
            pozycjaZnaku++;
        }

    }
    else
        iloscWystapien = 0;
    return iloscWystapien;

}

int obliczIleTakichSamychZnakowWystepujeObokSiebie (string wyrazDoSkrocenia, int pozycja)
{
    int iloscTakichSamychZnakow = 1;

    while ((wyrazDoSkrocenia[pozycja] == wyrazDoSkrocenia[pozycja + 1]) && (!isdigit(wyrazDoSkrocenia[pozycja])))
    {
        iloscTakichSamychZnakow++;
        pozycja++;
    }

    return iloscTakichSamychZnakow;
}

string skracanieWyrazow(string wyrazDoSkrocenia, int minimalnaIloscZnakowOdKtorychNalezySkracac)
{
    int dlugosc = wyrazDoSkrocenia.length();

    int iloscWystapien = 1;
    char powtarzajacySieZnak;

    for (int i = 0; i < dlugosc; i++)
    {
        if ( !isdigit(wyrazDoSkrocenia[i]) && obliczIleTakichSamychZnakowWystepujeObokSiebie(wyrazDoSkrocenia, i) >= minimalnaIloscZnakowOdKtorychNalezySkracac)
        {
            iloscWystapien = obliczWystapieniaWybranegoZnaku(wyrazDoSkrocenia, i);
            powtarzajacySieZnak = wyrazDoSkrocenia[i];
            wyrazDoSkrocenia.replace(minimalnaIloscZnakowOdKtorychNalezySkracac, iloscWystapien, powtarzajacySieZnak + konwersjaIntNaString(iloscWystapien));
            dlugosc = wyrazDoSkrocenia.length();
        }

    }
    return wyrazDoSkrocenia;
}


int main()
{
    string wyraz;
    int liczbaTestow;
    int minimalnaIloscZnakowOdKtorychNalezySkracac;

    cin >> liczbaTestow;

    for (int i = 0; i < liczbaTestow; i++)
    {
        cin >> wyraz;
        cin >> minimalnaIloscZnakowOdKtorychNalezySkracac;
        cout << skracanieWyrazow(wyraz, minimalnaIloscZnakowOdKtorychNalezySkracac) << endl;
    }

    return 0;
}


0

Nie wiem czy o to Ci chodzi ale zobacz tak
wyrazDoSkrocenia.replace(i, iloscWystapien, powtarzajacySieZnak + konwersjaIntNaString(iloscWystapien));
dlugosc = wyrazDoSkrocenia.length();

0

Raczej nie ma przypadków złożonych. Wszystko opiera się na przykładach tj. aaaaaaaa, załóżmy skracanie od 4. i powinno być a4

0

Spróbuj zmienić funkcję skracanieWyrazow na następującą wersję:

string skracanieWyrazow(string wyrazDoSkrocenia, int minimalnaIloscZnakowOdKtorychNalezySkracac)
{
    int dlugosc = wyrazDoSkrocenia.length();

    int iloscWystapien = 1;
    char powtarzajacySieZnak;

    string result = ""; // pusty string z którego zbudujemy rozwiąznie

    for (int i = 0; i < dlugosc; i++)
    {
        if ( !isdigit(wyrazDoSkrocenia[i]) && obliczIleTakichSamychZnakowWystepujeObokSiebie(wyrazDoSkrocenia, i) >= minimalnaIloscZnakowOdKtorychNalezySkracac)
        {
            iloscWystapien = obliczWystapieniaWybranegoZnaku(wyrazDoSkrocenia, i);
            result += wyrazDoSkrocenia[i];
            result += konwersjaIntNaString(iloscWystapien);
            i+= iloscWystapien;
        }
        else
        {
            result += wyrazDoSkrocenia[i];
        }

    }
    return result;
}
0
string skracanieWyrazow(string wyrazDoSkrocenia, int minimalnaIloscZnakowOdKtorychNalezySkracac)
{
    int dlugosc = wyrazDoSkrocenia.length();
    string result;
    int iloscWystapien = 1;
    char powtarzajacySieZnak;
    result = wyrazDoSkrocenia[0] + std::to_string(max(dlugosc - minimalnaIloscZnakowOdKtorychNalezySkracac + 1,0));
   
   return result;
}
```

To moze tak?

BTW dla przypadku aaaaaa 3 wynik podajesz a4 a dla aaaaaaaa 4 wynik a4. To ma być włącznie z ta pozycja czy wyłacznie?
0

Polecenie do zadania: Zmodyfikuj program tak aby oprócz wyrazDoSkrocenia przyjmował drugą zmienną całkowitą o nazwie iloscZnakow określającą to, od jakiej minimalnej ilości znaków ma zacząć skracać wyraz. Stwórz taką funkcję, do której będziemy podawać wyrazDoSkrocenia oraz to od jakiej ilości znaków ma nastąpić skrócenie. Na wyjściu ma być zwrócony skrócony wyraz.
Ilość znaków to minimalnaIloscZnakowOdKtorychNalezySkracac

Więcej przykładów: [aaa, '1'] -> a3, [nnnnnn, '5'] -> n2, [wwwwwwww, '5'} -> w4

0

Dlaczego jest taka funkcja "max(dlugosc - minimalnaIloscZnakowOdKtorychNalezySkracac + 1,0)"?

1

Nie rozumiem nadal polecenia. Nie chcę wchodzić na razie w kod, więc po prostu zapytam o spójność przypadków, które napisałaś.

Polecenie do zadania:

Zmodyfikuj program tak aby oprócz wyrazDoSkrocenia przyjmował drugą zmienną całkowitą o nazwie iloscZnakow określającą to, od jakiej minimalnej ilości znaków ma zacząć skracać wyraz. Stwórz taką funkcję, do której będziemy podawać wyrazDoSkrocenia oraz to od jakiej ilości znaków ma nastąpić skrócenie. Na wyjściu ma być zwrócony skrócony wyraz. Ilość znaków to minimalnaIloscZnakowOdKtorychNalezySkracac

Zakładam, że skrócenie (nieopisane w podanym poleceniu) następuje poprzez zamianę każdego podciągu wyrazu na wejściu o elementach zawierających ten sam znak na jedno wystąpienie tego znaku, za którym stoi liczba jego wystąpień.

UPDATE: Zakładam ponadto, że "minimalna ilość znaków" oznacza minimalną liczbę takich samych znaków w podciągu.

Przypadki, które opisałaś:

  • Wejście: "aaaaaa", 3. Wyjście: a4. Według powyższego założenia powinno być albo aaaa3, albo a6.
  • Wejście: "aaaaaaaa", 4. Wyjście: a4. Według powyższego założenia powinno być albo aaaaa4, albo a8.
  • Wejście: "aaabbbb", 4 Wyjście: a4. Według powyższego założenia powinno być aaab3 aaab4.
  • Wejście: "aaa", 1. Wyjście: a3. Zgadza się z powyższym założeniem.

Czy dobrze rozumiem skracanie, czy może powinienem wejść w kod? Jeśli dobrze rozumiem, to czy przypadki nie powinny być spójne?


UPDATE2:

Według naszych najnowszych doniesień, podanych przez @Magda Pietrzykowska w komentarzu do tego posta, rewiduję swoje rozumienie. Dodatkowa informacja jest: założeniem skracania jest, by na wyjściu były ignorowane znaki przed podanym numerem znaku. Rozumiem "numer" przez zwykły numer, a nie indeks (jak w tablicy w C++), czyli liczę znaki od 1, a nie od 0. (Nie powinno mieć to większego znaczenia dla algorytmu, ale musi być doprecyzowane przed rozpoczęciem).

  • Wejście: "aaaaaa", 3. Z dodatkowym założeniem wyjście powinno być: a3.
  • Wejście: "aaaaaaaa", 4. Z dodatkowym założeniem wyjście powinno być: a4.
  • Wejście: "aaabbbb", 4 Z dodatkowym założeniem wyjście powinno być: b3.
  • Wejście: "aaa", 1. Z dodatkowym założeniem wyjście powinno być: a3.

UPDATE3:

Według naszych najnowszych doniesień, podanych przez @Magda Pietrzykowska w komentarzu do tego posta, ponownie rewiduję swoje rozumienie. Druga dodatkowa informacja jest: założeniem skracania jest, że znak o podanym numerze wlicza się do skracanego podciągu (u mnie się nie wliczał do tej pory).

  • Przypadek 1:
    • Wejście: "aaaaaa", 3.
    • Wyjście: a4.
    • Dlaczego: Wyraz ma przynajmniej 3 znaki, a więc w podciągu aaaaaa (sześć znaków a) pierwsze dwa znaki zostają pominięte, a następne cztery zostają skrócone do a4.
  • Przypadek 2:
    • Wejście: "aaaaaaaa", 4.
    • Wyjście: a5.
    • Dlaczego: Wyraz ma przynajmniej 4 znaki, a więc w podciągu aaaaaaaa (osiem znaków a) pierwsze trzy znaki zostają pominięte, a następne pięć zostaje skrócone do a5.
  • Przypadek 3:
    • Wejście: "aaabbbb", 4.
    • Wyjście: a1b4 b4.
    • Dlaczego: Wyraz ma przynajmniej 4 znaki, a więc: 1) w podciągu aaa (trzy znaki a) pierwsze dwa cztery znaki zostają pominięte, a ponieważ ten podciąg ma mniej znaków niż zostało pominiętych, nic nie zostaje zwrócone; 2) w podciągu bbbb (cztery znaki b) wszystkie znaki zostają skrócone do b4.
  • Przypadek 4:
    • Wejście: "aaa", 1.
    • Wyjście: a3.
    • Dlaczego: Wyraz ma przynajmniej 1 znak, a więc w podciągu aaa (trzy znaki a) pierwszych zero znaków zostaje pominiętych, a następne trzy zostają "skrócone" do a3.
0

O coś takiego chodzi?
link

0

To kod w JavaScripcie – spróbuj zrozumieć sam algorytm, a nie język. Komentarze dałem po angielsku, ale powinnaś zrozumieć. Jakby coś, to pytaj.

Ten algorytm odzwierciedla ostatnią wersję, którą opisałem wyżej (po aktualizacji o godzinie 02:52).

// Define the input
let inputCases = [
    {
        word: "aaaaaa",
        minWordLengthToShorten: 3
    },
    {
        word: "aaaaaaaa",
        minWordLengthToShorten: 4
    },
    {
        word: "aaabbbb",
        minWordLengthToShorten: 4
    },
    {
        word: "aaa",
        minWordLengthToShorten: 1
    }
];

function shorten(word, minWordLengthToShorten) {
    let startCharacterIndex = minWordLengthToShorten - 1;
    let outputWord = word[startCharacterIndex];
    let sameCharactersCount = 1;

    for (let i = startCharacterIndex + 1; i < word.length; ++i) {
        if (word[i] === word[i - 1]) {
            // This character is the same as the previous one

            ++sameCharactersCount;

            if (i === word.length - 1) {
                // This is the last character

                outputWord += sameCharactersCount;
            }
        } else {
            // This character is different than the previous one

            outputWord += sameCharactersCount;
            outputWord += word[i];
            sameCharactersCount = 1;
        }
    }

    return outputWord;
};

for (let i = 0; i < inputCases.length; ++i) {
    // Compute the shortened word
    let shortenedWord = shorten(
        inputCases[i].word,
        inputCases[i].minWordLengthToShorten
    );

    // Print the shortened word
    console.log(
        "{"
        + inputCases[i].word
        + ", "
        + inputCases[i].minWordLengthToShorten
        + "} ---> "
        + shortenedWord
    );
}

Tutaj wersja działająca online (by zobaczyć wynik, musisz nacisnąć F12 i wejść w zakładkę Console):
https://jsfiddle.net/7owef2bg/1/

Zastrzegam: nie wiem, czy ten algorytm jest poprawny dla zadania, ale działa poprawnie dla przedstawionych powyżej przeze mnie czterech przypadków (po aktualizacji o godz. 02:52).

1

Takie coś naskrobałem :>

#include <iostream>
#include <algorithm>
#include <tuple>
#include <string>
#include <string_view>

using namespace std;

template<class ForwardIt>
ForwardIt skip_adjacent(ForwardIt first, ForwardIt last, const typename iterator_traits<ForwardIt>::value_type& value)
{
    if (first == last)
        return first;
    while (first != last) {
        if (*first != value)
            return first;
        ++first;
    }
    return last;
}

tuple<char, size_t> compress_subword(string_view text)
{
    auto next = skip_adjacent(begin(text), end(text), text.front());
    return {text.front(), distance(begin(text), next)};
}


string shorten(string_view text, size_t offset)
{
    string result;
    if (auto [chr, len] = compress_subword(text); len < offset) {
        copy_n(begin(text), offset - 1, back_inserter(result));
    }
    text.remove_prefix(offset - 1);
    while (!text.empty()) {
        auto [chr, len] = compress_subword(text);
        result += chr;
        result += to_string(len);
        text.remove_prefix(len);
    }
    return result;
}

void test(string_view text, size_t offset)
{
    cout << '[' << text << ',' << offset << "] -> " << shorten(text, offset) << '\n';
}


int main(int, char**)
{
    test("aaaaaa", 3);
    test("aaa", 1);
    test("nnnnnn", 5);
    test("wwwwwwww", 5);
    test("aaabbbb", 4);
    test("aaabbbbbbcc", 4);
    return 0;
}

link

0

Podaję nową wersję algorytmu, który zamieściłem powyżej. Uwzględniam teraz nową wytyczną: (...) znaki przed podanym numerem znaku powinny pomijane w skracaniu, ale NIE powinny być pomijane w wyniku (w wersji powyżej nie uwzględniłem jej). Dodałem jedną linijkę i zmieniłem też jedną, obie oznaczyłem komentarzami, żeby było wiadomo.

PS. Dla wyjaśnienia: metoda napis.slice(x, y) zwraca podciąg danego napisu napis od indeksu x do indeksu y-1. Tutaj specyfikacja, jeśli będziesz zainteresowana: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/slice W tej specyfikacji nie jest napisane, co się dzieje, jeśli x === y (taki jest ostatni nasz przypadek); tutaj masz to wyjaśnione: https://stackoverflow.com/a/2243835/4752834

let inputCases = [
    {
        word: "aaaaaa",
        minWordLengthToShorten: 3
    },
    {
        word: "aaaaaaaa",
        minWordLengthToShorten: 4
    },
    {
        word: "aaabbbb",
        minWordLengthToShorten: 4
    },
    {
        word: "aaa",
        minWordLengthToShorten: 1
    }
];

function shorten(word = "", minWordLengthToShorten) {
    let startCharacterIndex = minWordLengthToShorten - 1;
    let charactersBeforeStartIndex = word.slice(0, startCharacterIndex); // this line was added
    let outputWord = charactersBeforeStartIndex + word[startCharacterIndex]; // this line was changed
    let sameCharactersCount = 1;

    for (let i = startCharacterIndex + 1; i < word.length; ++i) {
        if (word[i] === word[i - 1]) {
            // This character is the same as the previous one

            ++sameCharactersCount;
        } else {
            // This character is different than the previous one

            outputWord += sameCharactersCount;
            outputWord += word[i];
            sameCharactersCount = 1;
        }

        if (i === word.length - 1) {
            // This is the last character

            outputWord += sameCharactersCount;
        }
    }

    return outputWord;
};

for (let i = 0; i < inputCases.length; ++i) {
    // Compute the shortened word
    let shortenedWord = shorten(
        inputCases[i].word,
        inputCases[i].minWordLengthToShorten
    );

    // Print the shortened word
    console.log(
        "{"
        + inputCases[i].word
        + ", "
        + inputCases[i].minWordLengthToShorten
        + "} ---> "
        + shortenedWord
    );
}

UPDATE: Poprawiłem algorytm zgodnie z uwagą @Mózg z komentarza. Przeniosłem instrukcję if z wnętrza drugiej instrukcji if na zewnątrz. Wcześniej, jeśli ostatnia litera była różna, algorytm nie wypisywał za nią liczby (1). Obecnie wypisuje.

1 użytkowników online, w tym zalogowanych: 0, gości: 1