Du må være registrert og logget inn for å kunne legge ut innlegg på freak.no
X
LOGG INN
... eller du kan registrere deg nå
Dette nettstedet er avhengig av annonseinntekter for å holde driften og videre utvikling igang. Vi liker ikke reklame heller, men alternativene er ikke mange. Vær snill å vurder å slå av annonseblokkering, eller å abonnere på en reklamefri utgave av nettstedet.
  4 5223
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
For å fortsette den relativt populære "serien", kommer jeg med en ny oppgave.

Ditt oppdrag, dersom du velger å akseptere det, er å skrive en funksjon som tar inn et heltall og returnerer et norsk uttrykk for dette tallet. Det vil si:

f(1) = "en"
f(20) = "tjue"
f(493) = "fire hundre og nittitre"

Jeg har forberedt litt testdata du kan bruke under utvikling og for å kontrollere implementasjonen din.

https://gist.github.com/robhol/c57a9...959cdc9a29fa15

Implementasjonen din må...
... støtte tall fra 0 til 10 billioner (inkl.) og de negative motstykkene til disse tallene.

... bruke riktig bøyning
ett hundre, ett tusen, en million, to hundre, to millioner

... bruke komma og "og" på riktig sted
"to hundre og førtito", "fire tusen, to hundre og førtito", "en million og tretten", NB "en million, fire tusen"

... bruke "long scale"
"en million", "en milliard", "en billion" osv

En anbefalt men valgfri del av oppgaven er å lage noe som går gjennom testdataene og sammenlikner svaret fra implementasjonen din med fasit for det aktuelle tallet, og printer ut eventuelle forskjeller. Det er opp til deg om du går gjennom testdataene som de er, eller oversetter dem til aktuell syntaks i språket du bruker.

Hvis noen har kommentarer til "fasit" eller ser feil i denne, er det bare å si ifra.

Min løsning blir publisert etter hvert, og er skrevet i Python. Det er mulig jeg også skriver en versjon i C# - hvis jeg gidder.
Morsom oppgave. Jeg gikk for en rekursiv variant i C.
Koden er kanskje ikke veldig lesbar. Den grunnleggende tanken er at hele tallet gis til getText-funksjonen som vil komme frem til svaret ved å kalle på seg selv med mindre deloppgaver når det trengs.

Nå må tilbake til jobb!

Kode

/* Tar en serie med tall som argument
 * Printer '[tallverdi]: norsk tallord'
 */ 

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <math.h>
#include <string.h>

const char atoms[20][8] = {
	"null", "en", "to", "tre", "fire", "fem", "seks", "sju",
	"åtte", "ni", "ti", "elleve", "tolv", "tretten", "fjorten",
	"femten", "seksten", "sytten", "atten", "nitten"
};
const char tens[8][7] = {
	"tjue", "tretti", "førti", "femti", "seksti", "sytti", "åtti", "nitti"
};
char bigs[16][9] = { "" };
int places[5]={2, 3, 6, 9, 12};

void assignBigs() {
	strncpy(bigs[2], "hundre", 6);
	strncpy(bigs[3], "tusen", 5);
	strncpy(bigs[6], "million", 7);
	strncpy(bigs[9], "milliard", 8);
	strncpy(bigs[12], "billion", 7);
};

int64_t pow64(int64_t n, int j) {
	int i;
	int64_t ret=1;
	for (i=0;i<j;i++) {
		ret*=n;
	}
	return ret;
}

int intlen64(int64_t n) {
	char  s[16]="";
	sprintf(s, "%" PRId64, n);
	return strlen(s);
}

char *getText(char *str, int64_t d, int len) {
	int cb; // closest big
	int i;
	if (d<20) {
		strcat(str, atoms[d]);
		char prefix[20]="";
		return str;
	}
	else if (len<3) {
		int i = d%10;
		strcat(str, tens[d/10-2]);
		if (i>0) strcat(str, atoms[i]);
		return str;
	}
	
	cb = len-1;
	for (i=4;cb-places[i]<0;i--) {}
	cb = places[i];

	int64_t next;
	int cut = 1;

	cut = d/pow64(10, cb);
	char buff[200]="";
	if (cb<=3 && cut ==1) strcat(str, "ett ");
	else {
		strcat(str, getText(buff, cut, len-cb));
		strcat(str, " ");
	}
	strcat(str, bigs[cb]);
	if (cb>5 && cut>1) {
		strcat(str, "er");
	}
	
	next = d-cut*pow64(10, cb);
	if (next == 0) return str;
	buff[0] = '\0';
	getText(buff, next, intlen64(next));
	if (buff != "null") {
		if (next<100) strcat(str, " og ");
		else strcat(str, ", ");
		strcat(str, buff);
	}

	return str;
		
}

int main(int argc, char *argv[]) {
	int64_t d;
	char result[1000];
	for (int i=1;i<argc;i++) {
		d=0;
		sscanf(argv[i], "%" PRId64, &d);
		assignBigs();
		result[0] = '\0';
		if (d<0) {
			d *= -1;
			strcpy(result, "minus ");
		}
		getText(result, d, intlen64(d));
		printf("%" PRId64, d);
		printf(": %s\n", result);
	}
	return 0;
}
▼ ... over en uke senere ... ▼
Jeg er en relativt uerfaren programmerer, så dette er skrevet basert på den kunnskapen jeg fikk av et introduksjonskurs til Python 2.7 på UiO. (pluss et fysikkemne). Det består av to skript hvor det ene skriptet bare printer omgjøringene fra det andre. Kunne helt sikkert blitt skrevet på en bedre måte haha. Det første programmet tar å bestemmer fortegn, det andre programmet består av et sett funksjoner som utfører selve omgjøringen. (Nederst i det siste skriptet ligger et sett med funksjoner som bestemmer om det skal være komma eller og.) Det står "from numbers import *" øverst i det første fordi det andre heter "numbers.py".

Kode

from numbers import *
import sys


def numbers(n):
	if len(n) == 1:
		return number1(n)
	elif len(n) == 2:
		return number2(n)
	elif len(n) == 3:
		return number3(n)
	elif len(n) == 4:
		return number4(n)
	elif len(n) == 5:
		return number5(n)
	elif len(n) == 6:
		return number6(n)
	elif len(n) == 7:
		return number7(n)
	elif len(n) == 8:
		return number8(n)
	elif len(n) == 9:
		return number9(n)
	elif len(n) == 10:
		return number10(n)
	elif len(n) == 11:
		return number11(n)
	elif len(n) == 12:
		return number12(n)
	elif len(n) == 13:
		return number13(n)
	elif len(n) == 14:
		return number14(n)

def sign(n):
	n = str(n)
	if n[0] == '-':
		return 'minus ' + numbers(n[1:])
	else:
		return numbers(n)

def f(n):
	return sign(n)


n = raw_input('Tall mellom -10 billioner og 10 billioner: ')
print f(n)

Kode

# -*- coding: utf-8 -*-

#One function for each possible number length
def number1(n):
	if n == '0':
		number = 'null'
	elif n == '1':
		number = 'en'
	elif n == '2':
		number = 'to'
	elif n == '3':
		number = 'tre'
	elif n == '4':
		number = 'fire'
	elif n == '5':
		number = 'fem'
	elif n == '6':
		number = 'seks'
	elif n == '7':
		number = 'syv'
	elif n == '8':
		number = 'åtte'
	elif n == '9':
		number = 'ni'
	return number

def number2(n):
	if n[0] == '0':
		number = number1(n[1:])
	else:
		if n[0] == '1':
			if n[-1] == '0':
				number = 'ti'
			elif n[-1] == '1':
				number = 'elleve'
			elif n[-1] == '2':
				number = 'tolv'
			elif n[-1] == '3':
				number = 'tretten'
			elif n[-1] == '4':
				number = 'fjorten'
			elif n[-1] == '5':
				number = 'femten'
			elif n[-1] == '6':
				number = 'seksten'
			elif n[-1] == '7':
				number = 'sytten'
			elif n[-1] == '8':
				number = 'atten'
			elif n[-1] == '9':
				number = 'nitten'

		elif n[0] == '2':
			number = 'tjue'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '3':
			number = 'tretti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '4':
			number = 'førti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '5':
			number = 'femti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '6':
			number = 'seksti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '7':
			number = 'sytti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '8':
			number = 'åtti'
			if n[-1] != '0':
				number += number1(n[-1])
		elif n[0] == '9':
			number = 'nitti'
			if n[-1] != '0':
				number += number1(n[-1])
	return number
	
	
def number3(n):
	if n[0] == '0':
		number = number2(n[1:])
	else:
		if n[0] == '1':
			number = 'ett hundre'
		else:
			number = number1(n[0])+' hundre'
		if int(n[1:]) != 0:
			number += ' og ' + number2(n[-2:])
	return number
			

def number4(n):
	if n[0] == '0':
		number = number3(n[1:])
	else:
		if n[0] == '1':
			number = 'ett tusen'
		else:
			number = number1(n[0]) + ' tusen'
		number += ogcomma(n)
	return number
		
		
def number5(n):
	if n[0] == '0':
		number = number4(n[1:])
	else:
		number = number2(n[0:2]) + ' tusen'
		number += ogcomma(n)
	
	return number
	

def number6(n):
	if n[0] == '0':
		number = number5(n[1:])
	else:
		number = number3(n[0:3]) + ' tusen'
		number += ogcomma(n)
	return number
	
	
def number7(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		if n[0] == '1':
			number = number1(n[0]) + ' million'
		else:
			number = number1(n[0]) + ' millioner'
		number += comma(n)
	return number


def number8(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		number = number2(n[0:2]) + ' millioner'
		number += comma(n)
	return number


def number9(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		number = number3(n[0:3]) + ' millioner'
		number += comma(n)
	return number
	
	
def number10(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		if n[0] == '1':
			number = number1(n[0]) + ' milliard'
		else:
			number = number1(n[0]) + ' milliarder'
		number += comma2(n)
	return number
	
	
def number11(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		number = number2(n[0:2]) + ' milliarder'
		number += comma2(n)
	return number


def number12(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		number = number3(n[0:3]) + ' milliarder'
		number += comma2(n)
	return number


def number13(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		if n[0] == '1':
			number = number1(n[0]) + ' trillion'
		else:
			number = number1(n[0]) + ' trillioner'
		number += comma3(n)
	return number
	
	
def number14(n):
	if n[0] == '0':
		number = number6(n[1:])
	else:
		number = number2(n[0:2]) + ' trillioner'
		number += comma3(n)
	return number

#defines where to put the comma og og
def ogcomma(n):
	if int(n[1:]) != 0:
		if n[-3] == '0':
			return ' og ' + number3(n[-3:])
		else:
			return ', ' + number3(n[-3:])


def comma(n):
	if int(n[-6:-3]) != 0 and int(n[1:]) != 0:
		return ', ' + number6(n[-6:])
	else:
		return ogcomma(n)


def comma2(n):
	if int(n[-9:-6]) != 0 and int(n[1:]) != 0:
		return ', ' + number9(n[-9:])
	else:
		return comma(n)

		
def comma3(n):
	if int(n[-12:-9]) != 0 and int(n[1:]) != 0:
		return ', ' + number12(n[-12:])
	else:
		return comma2(n)
Det var en liten feil i programmet der. I det andre skriptet skal det første if-statementet henvise til det forrige nummeret. Fra number8(n) og nedover er dette feil. Var for sent ute å se det og kan ikke lenger redigere... Copy-Paste is a bitch

EDIT: Ser nå at programmet ikke funker likevel... Flaut
Sist endret av Likyhane; 12. juli 2017 kl. 15:56. Grunn: Automatisk sammenslåing med etterfølgende innlegg.
NOOOOOOOOOOOOOOOOOO-
robhol's Avatar
Trådstarter
Huhei, denne hadde gått i glemmeboka igjen.

Her er min løsning, denne i Python 3. Den ender opp på 40-ish linjer med ren logikk, resten er dict-definisjoner og testkode.
Det er veldig mulig jeg har gjort ting som ikke er veldig "pytoniske" og enkelte ting som bare er grælstygge, men det funker.

https://gist.github.com/robhol/0a2d1...a3c0866ef742ed
Forsøkte meg på en iterativ løsning, men merket at hjernen ikke var helt med på det. Fikk noe som virker, men det er åpenbart rom for forbedring: https://gist.github.com/anonymous/8d...7a7722599a24ba