Call For Help Numpad


#1

In questo probleme l’input può essere costituito da un numero che ha come prima cifra il numero 0, come faccio a prenderlo? Se lo prendo con int lo 0 sparisce se lo prendo come char/string dopo non posso farci le operazioni. (C++)


#2

Hai provato a leggere il numero come stringa ed a chiamare la funzione string to int, std::stoi(string), definita in string, ogni volta che devi usare il numero in essa contenuto?

Documentazione std::stoi -> http://www.cplusplus.com/reference/string/stoi/

Esempio

#include <string>
#include <iostream>
int main()
{
    std::string  la_mia_stringa = "0981";
    std::cout << std::stoi(la_mia_stringa) + 9;
}
// Output 990

P.S.: Dovrebbero esistere anche altre funzioni base del tipo string to float se dovessero servire


#3

Come mi aiuta questa funzione? A me sembra come prenderlo direttamente in int, in quanto l’output non è 0990 ma 990


#4

Ok, sarò sincero, non avevo letto il problema e pensavo ti bastasse tenerti lo zero finché non iniziavi ad eseguire calcoli. Però, per quanto penso sia una pessima idea dal punto di vista di tempo, quello che mi viene in mente è relativamente semplice:

  • Fai l’operazione necessaria con la stringa passata ad intero
  • Usi la funzione opposta, to_string, per ritrasformare l’intero in stringa
  • Confrontando le dimensioni del risultato con quella della stringa, puoi sapere se hai perso o no lo 0 (e anche quanti 0 in realtà), in questo caso puoi semplicemente ri-aggiungerlo concatenando alla stringa ‘0’ la stringa attuale.

Esempio:

#include <string>
#include <iostream>

int main()
{
    std::string la_mia_stringa = "0981";
    int numero = std::stoi(la_mia_stringa) + 9;
    std::string risultato = std::to_string(numero);
    for (int i = risultato.size(); i < la_mia_stringa.size(); i++)
    {
        risultato = '0' + risultato;
    }
    std::cout << risultato;
}
// Risultato: 0990

Nel caso si stiano sommando 2 stringhe entrambe inizianti con 0, dovrebbe bastare eseguire il controllo solo su quella di dimensione maggiore. Ovviamente puoi trasformare tutto questo in una funzione.

P.S: Dopo aver letto il problema mi viene in mente di usare un grafo: ogni numero è un nodo connesso con i numeri vicini. Dopo aver letto il numero come stringa, non è difficile convertirlo in un vettore. Una volta avuto il vettore, sapendo il nodo su cui è la tua formica, devi arrivare al prossimo numero del vettore.

Conversione Stringa in Vettore

#include <iostream>
#include <vector>
#include <iostream>

std::vector<int> StringToVector(std::string la_mia_stringa)
{
// Uso il costruttore parametrico per iniziallizzare un vettore di 0 elementi
std::vector<int> out(0);
/* Non so se conosci questa sintassi, ma è equivalente a 
 * (int i = 0; i < la_mia_stringa.size(); i++)
 * ogni richiamo a x, sarà equivalente a richiamare la_mia_stringa[i]
 *
 * P.S: effettivamente non ricordo se gli elementi di una stringa di cpp vengono
 * considerati a loro volta std::string oppure semplici char, lascio il codice per il primo caso
 */
for(std::string x : la_mia_stringa) // In caso di char diventa for (char x : la_mia_stringa)
{
out.push_back(std::stoi(x))
// Ovviamente in caso di char bisogna eseguire il casting in modo diverso
}
return out;
}

#5

Vorrei far notare che in questo esercizio il “numero” in ingresso ha 1 000 000 cifre e che nessun dato primitivo riuscirebbe a memorizzarlo. Inoltre l’informazione utile in input non è l’insieme dei numeri ma la sequenza delle cifre. Suggerisco di leggere l’ input come stringa e di cambiare il valore del char in int:

#include <bits/stdc++.h>

using namespace std;

int main(){
    string N;
    cin >> N;
    for(int i = 0; i < (int) N.size(); i++){
        int cifra = N[i] - '0';
        // qualcosa
    }
    return 0;
}

Inoltre concatenare due stringhe è un’operazione che richiede O(N) di tempo, dove N è il numero di caratteri da accodare. Fatta N volte questa operazione renderebbe il codice O(N^2).

L’idea di trattare questo esercizio come un grafo è giusta.


#6

Non dovrebbe essere molto diverso dall’ultimo codice che ho scritto, quello con la funzione StringToVector, o sbaglio? (Beh, a parte la sintassi, che ripensandoci è molto più probabile che i singoli elementi siano char e non stringhe)

Ok, sorry, effettivamente ricopiare il tutto in un vettore è inutile, basta eseguire il codice al posto di “// Qualcosa” (Oppure non ho capito nulla, il che è probabile). Però non ben ho capito il senso del casting ad intero di N.size(). Il metodo std::string::size non restituisce interi da solo?


#7

In realtà ho visto il codice scritto in quella maniera e ho rinunciato a leggerlo LOL
Ora che ho letto il secondo codice, posso dirti che sono presenti degli errori. La funzione accetta il parametro la\_mia\_stringa che è effettivamente una stringa, ma non un contenitore di stringhe. Quindi il ciclo presente nella funzione non ha senso e dovrebbe risultare in errori di compilazione. Nel caso in avessi voluto iterare per ogni carattere presente nella stringa, la funzione stoi non è adeguata per cambiare il carattere in intero.

vector <int> StringToVector(string la_mia_stringa){
	vector <int> ret;
	for(char &i : la_mia_stringa){
		ret.push_back(i - '0');
	}
	return ret;
}

Bhe dipende da cosa devi fare, e come vuoi farlo.

Il metodo size restituisce size_t e il mio compilatore mi da un sacco di warning quando faccio le operazione con altri interi, per questo faccio il casting in int.


#8

In effetti lo immaginavo infatti avevo scritto

* P.S: effettivamente non ricordo se gli elementi di una stringa di cpp vengono
* considerati a loro volta std::string oppure semplici char, lascio il codice per il primo caso

Però va be’ l’importante è che ci siamo capiti.

Un’ultima curiosità, per l’accesso agli elementi della stringa, usi le parentesi quadre e non il metodo std::string::at(), solo per abitudine con gli array normali del C o perché è molto più veloce (In effetti le parentesi non eseguono alcun controllo per stabilire se l’indice è valido o no, mentre std::string::at() sì)


#9

Non avevo letto i commenti, scusami :sweat_smile:
In realtà non sono informato sui dettagli d’implementazione tra la funzione std::string::at() e l’operatore delle parentesi quadre. Di solito uso le quadre perché le scrivo molto più velocemente delle funzione at. L’unico utilizzo che vedo nella funzione è se hai errori di memoria e non capisci dove sono presenti, anche se in quel caso sono solito a usare assert vari.


#10

Non ti preoccupare, fa niente :wink:

In effetti l’unica differenza è questa:


Get character in string

Returns a reference to the character at position pos in the string.

The function automatically checks whether pos is the valid position of a character in the string (i.e., whether pos is less than the string length), throwing an out_of_range exception if it is not

Strong guarantee: if an exception is thrown, there are no changes in the string.

***

Fonte: http://www.cplusplus.com/reference/string/string/at/
Eseguendo un controllo dovrebbe essere più lento delle parentesi, quindi dubito ne valga la pena in un esercizio di questa piattaforma, ma magari conviene in un progetto piuttosto lungo

Comunque, grazie di tutto


#11

Grazie mille, 100 punti!