Jednocyfrowa suma

0

Na ferie dostałem zadanie do zrobienia i w nie wiem o co w nim chodzi , prosze o jakas pomoc.

Napisz program, który dla podanej na standardowym wejściu liczb całkowitej n wypisze jednocyfrową sumę jej cyfr. (liczba całkowite typu int).

Przykład
Dla danych wejściowych:

18,25,793

poprawnym rozwiązaniem jest:

9,7,1

0

Dziękujemy za tak wyczerpujące informacje :/ Zdradź przynajmniej w jakim języku, to może ktoś będzie w stanie coś pomóc!!!

0

liczba 18 czyli 1+8=9
liczba 25 czyli 2+5=7

i ostatnia prawdopodobnie:
liczba 793 czyli 7+9+3=19
.. 19= 1+9=10
.. 10= 1+0=1

Całość zrobisz za pomocą div mod i pętli np. while.

Jeżeli nie rozumiesz jeszcze to poszukaj w numerologi, pamiętam, że tam tak samo przeliczało się jakieś cyferki..

0

Wersja 1, mało efektywna i mało elegancka:

object Main extends Application {
  def contract(number: String): String = {
    if (number.length < 2)
      return number
    contract(number.map(_.asDigit).sum.toString)
  }
  print(contract(Console.readLine))
}

Wersja 2, elegancka i efektywna, funkcje w funkcjach - fajny bajer:

object Main extends Application {
  def contract(sNumber: String) = {
    def contractInt(iNumber: Int): Int = {
      if (iNumber < 10)
        iNumber
      else 
        contractInt(iNumber % 10 + iNumber / 10)
    }
    contractInt(sNumber.map(_.asDigit).sum)
  }
  print(contract(Console.readLine))
}

Wersja 3, najmniej elegancka i średnio efektywna, ale za to najkrótsza:

object Main extends Application {
  var bigInt = BigInt(readLine)
  while (bigInt > 9) {
    bigInt = bigInt % 10 + bigInt / 10;
  }
  print(bigInt)
}

Ogłaszam konkurs na najbardziej elegancki kod rozwiązujący zadanie podobne do zadania z pierwszego posta, tzn wczytywany numer nie musi się mieścić w 32-bitach. Autor nie dopisał też jednej rzeczy: cyfry sumujemy rekurencyjnie, aż wyjdzie nam suma jednocyfrowa.

0
s = readline
s = s.chars.to_a.map(&:to_i).inject(&:+) until s.length < 2
puts s

Nie mam na razie pomysłu jak to poprawić by było trochę ładniejsze

0
long long int Potega(long long int Licz, int Wykl)
{
    for(int a = 1; a != Wykl; a++)
        Licz *= Licz;
    return Licz;
}
long long int DlugoscBardzoEleganckiejLiczby(long long int Liczba)
{
    long long int Dlug;
    for(Dlug = 1;; Dlug++)
        if(Potega(10, Dlug) > Liczba)
            return Dlug;
}
long long int JestemBardzoElegancki(long long int Liczba)
{
    int Dlugosc = DlugoscBardzoEleganckiejLiczby(Liczba);
    long long int Wynik = 0;
    for(int a = 0; a != Dlugosc; a++)
    {
        Wynik += Liczba % 10;
        Liczba /= 10;
    }
    return Wynik;
}
long long int Dlugosc(long long int Liczba)
{
    for(int a = 0; Liczba > 9; a++)
    {
         Liczba = JestemBardzoElegancki(Liczba);
         } 
    return Liczba;
    } 
0

Panowie, źle. To ma sumować rekurencyjnie, aż do uzyskania sumy jednocyforwej - tak jak w numerologii. Bez rekurencji program wyjdzie zbyt krótki:

object Main extends Application {
  print(readLine.map(_.asDigit).sum)
}
0

Mój już działa (bez rekurencji :P, tylko ładna pętelka).

0

Ruby v2:

i = readline.to_i
i = i % 10 + i / 10 until i < 10
puts i
0
long long get(long long n)
{
    long long suma=0;
    while(n!=0)
    {
        suma+=n%10;
        n/=10;
    }
    return suma;
}
int main()
{
    long long n;
    cin>>n;
    while(n>9)
        n=get(n);
    cout<<n;
    return 0;
}

wieżę, ze proste rozwiązania to dobre rozwiązania:D

0

Kod w C++, z powodu dużego popytu:

#include <iostream>

int contractInt(int number) {
    if (number < 10) {
        return number;
    } else {
        return contractInt(number % 10 + number / 10);
    }
}

int ctoi(char input) {
    return input - '0';
}

int main() {
    std::string input;
    std::cin >> input;
    int sum = 0;
    for (std::string::iterator i = input.begin(); i != input.end(); ++i) {
        sum += ctoi(*i);
    }
    std::cout << contractInt(sum);
    return 0;
}

Niestety nie udało mi się znaleźć w booście, ani STLu odpowiednika odpowiednika funkcji map z języków funkcyjnych i dlatego jest wielki for z dużą ilością "boilerplate code". Szukałem bardzo krótko więc może pominąłem.

0

Może by tak zabawić się w najbardziej poryty wariant rozwiązania? Niespecjalnie mam wenę, ale...

main = interact $ unlines . map (uncurry (!!) . (iterate (show . sum . map digitToInt) &&& length)) . lines
0

nie ma co zrobiliśmy prezent gościowi:D Ma rozwiązanie w prawie każdym języku.. Jakbym miał troszkę więcej czasy, to pokusiłbym się o ASM:)

0

Kurcze, gdyby nie projekt do zrobienia to może napisałbym to w BrainFucku.... :(

0

@up: czekamy na mistrzowskie rozwiązanie rekurencji w BF :D

Ja zarzucam asmem (dokładnie w MASM x86) (nie wiem, czy wypisywania liczb nie dało się szybciej):

.386
.model flat, stdcall
option casemap :none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\masm32.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\masm32.lib

.data
num db 1000 dup (0)
output db 11 dup (0)

.code
start:
	invoke StdIn, addr num, 997
	mov byte ptr [num+eax-2], 0
	lea eax, [num]
	push eax
	xor eax, eax
	xor ebx, ebx
	call numsum
	;na pewno dalo sie zrobic lepiej to wypisywanie liczb
	mov ebx, eax
	lea edi, [output]
	mov esi, 10
	petla_pisz_odwrotnie:
		cdq
		div esi
		add dl, 48
		mov byte ptr [edi], dl
		inc edi
		test eax, eax
		jnz petla_pisz_odwrotnie
	lea esi, [output]
	dec edi
	petla_odwroc:
		mov cl, byte ptr [esi]
		mov ch, byte ptr [edi]
		mov byte ptr [edi], cl
		mov byte ptr [esi], ch
		inc esi
		dec edi
		cmp esi, edi
		jl petla_odwroc
	invoke StdOut, addr output
	invoke ExitProcess, 0

numsum proc
;in  ESI	wskaznik na liczbe
;out EAX	suma cyfr
;EAX=0, EBX=0 (na poczatku)
	mov esi, [esp+4]
	cmp byte ptr [esi], 0
	jne numsumc
	ret
	numsumc:
	mov bl, [esi]
	add eax, ebx
	sub eax, 48
	inc esi
	push esi
	call numsum
	pop esi
	ret
numsum endp

end start
0

Jak ktoś to zrobi w Malbolge to stawiam mu piwo ;)

0

Średni ten kod w asm... No ale skoro jednak podchodzimy do sprawy poważnie to tym razem dam sensowne rozwiązanie w Haskellu:

module Main where

import Data.Char

main = interactLines $ head . dropWhile (not . null . tail) . iterate sumOfDigits
    where
       interactLines f = interact $ unlines . map f . filter (not . null) . lines
       sumOfDigits     = show . sum . map digitToInt

Jak :noframe nie działa to przynajmniej dorzucę chory wariant na kombinatorze punktu stałego i monadzie listy:

interactWithLines $ fix $ \f xs -> do x <- xs; case x of [_] -> [x]; _ -> f [sumOfDigits x]
0

No, niech będzie, ale jeszcze nikt nie walnął takiej fajnej funkcji JS:

function suma(e){
	return(function($){return $.length?$.charCodeAt(0)+arguments.callee($.substring(1))-48:0;})(e);
}
0

Ja zaproponuję taki kod w asmie:

format PE Console
entry _start

include 'C:\fasm\include\win32a.inc'

section '.text' code readable executable
_count:
	mov		eax, dword [esp+4]
	mov		ecx, dword [esp+8]
	mov		ebx, 10
@@:
	xor		edx, edx
	div		ebx
	add		ecx, edx
	or		eax, eax
	jnz		@b
	cmp		ecx, 10
	jb		@f
	mov		dword [esp+4], ecx
	mov		dword [esp+8], 0
	jmp		_count
@@:
	mov		eax, ecx
	ret

_start:
	push	0
	push	esp
	push	esp
	push	_ft
	call	[scanf]
	add		esp, 8
	call	_count
	add		esp, 8
	push	eax
	push	_ft
	call	[printf]
	add		esp, 8
	ret

section '.data' data readable writeable
	_ft:	db	"%d", 0

section '.idata' import readable
	library		msvcrt, 'msvcrt.dll'
	import		msvcrt, \
				scanf, 'scanf', \
				printf, 'printf'
0

Nareszcie, pół godziny się z tym męczyłem...

Uwaga, Befunge:

v  v/+55\+g99\p99<
>0&>:1`#v!_:55+% ^
     @.\<

Ktoś da mniej?

0
        div                ebx
        add                ecx, edx
        or                eax, eax
        jnz                @b
        cmp                ecx, 10
        jb                @f

Kilka uwag - or zajmuje tyle samo co test, wpływ na flagi ma podobny ale dodatkowo zapisuje wynik -> stosować test. Od add i test/or powinno być szybsze pojedyncze lea, które flag nie zmieni więc skok warunkowy będzie można zbudować w oparciu o stan eflags po div.

0

@mnbvcX:
Po pierwsze to zdaje się, że nie działa, bo np. suma('222222') zwraca 12, a powinno 3, bo 12 też powinno być zsumowane rekurencyjnie. Po drugie to nie bardzo widzę po co używasz tam wewnętrznej funkcji anonimowej. Ta zewnętrzna, suma, nic nie robi. Lepiej już wywalić funkcję anonimową (do której musisz się odnosić brzydko przez callee) i całą rekurencyjną robotę zwalić na funkcję suma. Pominę już używanie kodów znaków, bo to jest akurat o tyle fajne, że dzięki temu funkcja praktycznie działa na stringach i sumuje jedynie pojedyncze cyfry, więc zadziała także dla długich liczb.

Zapodam funkcyjno-rekurencyjną propozycję w JS, nie starając się by wszystko było jak najmniej czytelne i zapisane w jednej linii:

function sumDigits(number) {
  return (number < 10)
    ? number
    : sumDigits(
        String(number).split('').reduce(function(sum, digit) {
          return (+sum) + (+digit);
        })
      );
}

Do tego wczytanie "kilku" liczb rozdzielonych przecinkami i wyświetleniem wyniku:

var numbers = prompt('Podaj jedną lub kilka rozdzielonych przecinkami liczb, których cyfry mam zsumować').split(',');
var sums = numbers.map(sumDigits);
alert(sums);
0

n%9

0

(n%9==0)?9:n%9

0
function sumuj(a:string):string;
var i,wynik:longint;
begin
  wynik:=0;
  for i:=1 to length(a) do
    wynik:=wynik+ord(a[i])-ord('0');
  writestr(sumuj,wynik);
end;

var liczba:string;
begin
  readln(liczba);
  while length(liczba)>1 do
    liczba:=sumuj(liczba);
  writeln(liczba);
end.
0

@Azarien,

  1. Jakiekolwiek sumowanie cyfr i rekurencja jest zupełnie niepotrzebna (pierwszy zwrócił na to uwagę Xitami).
  2. Twój algorytm jest błędny dla liczb ujemnych.
0

Dzieki za pomoc. Mialo to byc napisane w c++(sory za pominiecie tego)

0

Wczytanie i wypisywanie napisz sam

int wynik=(n==0)?0:((abs(n)%9==0)?9:abs(n)%9);
0

Popsuliście zabawę Panowie :P

object Main extends Application {
  val sum = readLine.filter(_.isDigit).map(_.asDigit).sum
  print(if (sum % 9 == 0 && sum != 0) 9 else sum % 9)
}

Kurcze, że mi taki prosty trik do głowy nie wpadł :/ Ale niedawno robiłem podobne zadanie i tego typu triki nie chciały mi działać. Ale przynajmniej deus coś ciekawego pokazał :)

0

@bo:
@msm:
@Carlos Spicy-Weener:
Ja myślałem, że warunki konkursu były takie, żeby napisać to autorowi w każdym możliwym języku, tylko nie w tym, którym by chciał. Trudność polegała na tym, żeby przypadkiem na ten język nie wpaść i jeszcze dla zabawy dorzucić rekurencję (tbh nie zjarzyłem, że da się to zrobić nawet bez pętli).

Autor tematu napisał lakoniczną prośbę o gotowca, w której nie podał nawet języka. Konkurs miałby znaczenie dydaktyczne. Pokazałby, że ludzie owszem, są tu użytkownicy chętni do pomocy, ale nie do pisania gotowców. I że trzeba podawać więcej szczegółów, jak np. język w którym program ma być napisany.

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