Conversione di una stringa in lettere minuscole (senza funzioni incorporate in minuscole!)


25

L'obiettivo di questo code-golf è quello di creare un codice che consenta all'utente di immettere una stringa ASCII (contiene solo caratteri ASCII stampabili ) e il programma emette la variante minuscola di questa stringa.

Importante: NON ti è permesso usare una funzione integrata che converte la stringa (o solo un carattere) in minuscolo (come ToLower()in .NET, strtolower()in PHP, ...)! Tuttavia, puoi utilizzare tutte le altre funzioni integrate.

Un'altra nota importante: la stringa di input non contiene solo caratteri maiuscoli. La stringa di input è un mix di caratteri maiuscoli, caratteri minuscoli, numeri e altri caratteri ASCII stampabili .

In bocca al lupo!


4
sfortunatamente, dovrò rinunciare. Non sono un principiante.
John Dvorak,

@Jan: Beh, con il principiante in realtà intendevo dire che il livello di abilità di questo sarebbe 'principiante', non che solo i principianti avrebbero potuto entrare. Ho rimosso la parola "principiante" e sicuramente puoi entrare.
Programma FOX

1
Sono consentite le espressioni regolari? Solo GolfScript poteva battere s/./\L\0/g.
arte

3
@manatwork: sicuramente \Lè integrato?
marinus,

@manatwork: Sì, è consentita una regex.
Programma FOX

Risposte:


21

Shell - 10

Traduzione della soluzione Perl di @ Gowtham utilizzando /bin/tr.

tr A-Z a-z

Esecuzione di esempio:

% tr A-Z a-z <<<'Hello WORLD! @'
hello world! @

Cosa rende questa la risposta accettata, per curiosità? Gowtham aveva prima una soluzione di 10 caratteri ...
Ry

1
Sulla base della discussione su meta sembra che il ragionamento sia che la soluzione di Gowtham sia di 11 caratteri (perché la -pbandiera conta come uno). Sono d'accordo, però, sembra che meriti di più per essere accettato ..
FireFly

Ah, grazie - ha senso. Lo terrò a mente!
Ry,

53

Python 2.7 - 30 (con abuso di regole terribile e non dispiaciuto)

raw_input().upper().swapcase()

Come ha sottolineato una modifica anonima, puoi farlo 2726 in Python 3 :

input().upper().swapcase()

Sto abusando palesemente delle regole qui, ma ...

Importante: NON ti è permesso usare una funzione integrata che converte la stringa (o solo un carattere) in minuscolo (come ToLower()in .NET, strtolower()in PHP, ...)! Tuttavia, puoi utilizzare tutte le altre funzioni integrate.

Questo prende le stringhe e le copre in maiuscolo . Quindi, in una chiamata di metodo molto non correlata, inverte il caso della stringa, in modo che eventuali lettere minuscole diventino lettere maiuscole ... e scambia lettere maiuscole con lettere minuscole .


1
La soluzione Python 3 è di 26 caratteri.
Timtech,

@Timtech Non posso contare.

1
Non è solo indipendente. È molto indipendente.
Carter Pape,

1
Ciò produrrà strani risultati quando si incontrano testi che contengono i caratteri ß.
FUZxxl,

33

Perl - 11 10 caratteri.

y/A-Z/a-z/

y///è lo stesso di tr///!

In azione:

% perl -pe 'y/A-Z/a-z/' <<< 'Hello @ WORLD !'
hello @ world !

3
+1, per l'unica lingua della vita reale che ha battuto tutti quelli meno (?) Reali.
Behrooz,

In realtà sono 11 caratteri. L' -popzione è considerata come 1.
manatwork

@manatwork O dovrebbe essere contato come 2: -e p:)
Gowtham,

1 se si assume -e( perl -e-> perl -pe), 3 se si assume uno script ( perl-> perl -p).
nyuszika7h

10

Befunge-98 - 26 22 21 19

~:''-d2*/1-!' *+,#@

Si basa sul fatto che (c-39)/26è 1solo per i codici carattere di caratteri ASCII maiuscoli (presupponendo la divisione di numeri interi). Per ogni personaggio c, stampa c + (((c-39)/26)==1)*' '.

Sessione di esempio:

% cfunge lower.b98
hello WORLD!
hello world!
This is a TEST!!11 az AZ @[`{
this is a test!!11 az az @[`{

9

Python 3, 58

print("".join(chr(ord(x)+('@'<x<'[')*32)for x in input()))

Puoi spiegare come funziona? Sono davvero interessato a migliorare in Python. Non capisco come funziona il map(ord,input())bit.
asteri,

1
@JeffGohlke: mapapplica una funzione (in questo caso ord) a un interable e restituisce un iterable. È come una forma più breve di (ord(x) for x in input()).
Ry,

Fatto. Grazie per la spiegazione!
asteri,

1
La tua risposta segue lo spirito della domanda, ma la mia segue la lettera della domanda ...

Molto bella. Batti la mia soluzione di lunghezza 62 non pubblicata for c in input():print([c,(chr(ord(c)+32))]['@'<c<'['],end=''). Ho provato alcuni con ilmap(ord,input()) trucco, ma perso il moltiplicare il valore di verità per 32 e aggiungerlo al trucco con il codice del personaggio. Molto bella.
Steven Rumbalski l'

8

Ruby, 18 personaggi

Niente di veramente interessante.

gets.tr'A-Z','a-z'

(eseguito in IRB)

Solo per divertimento: una versione confusa:

$,=$* *' ';$;=$,.tr'A-Z','a-z';$><<$;

Esegui in questo modo:

c:\a\ruby>lowercase.rb Llamas are AMAZING!

Produzione

llamas are amazing!

7

J - 30

'@Z'(]+32*1=I.)&.(a.&i.)1!:1]1

J viene letto da destra a sinistra, quindi per scomporlo:

  1. Richiedi all'utente input: 1!:1]1
  2. Esegui algoritmo nello spazio punto-codice: &.(a.&i.)
  3. Identificare l'intervallo di caratteri per ogni lettera; i caratteri tra i punti di codice "@" e "Z" sono considerati maiuscoli:1=I. .
  4. Per ogni punto di codice maiuscolo, aggiungere 32: ]+32* ...
  5. Nota che il passaggio (2) crea un passaggio implicito (5): abbiamo iniziato proiettando dal dominio del carattere al numero intero, quindi ora che abbiamo finito, mappiamo quei numeri interi sui caratteri.

Ovviamente questa particolare implementazione considera solo ASCII; ma l'approccio potrebbe essere esteso almeno al piano multilingue di base in Unicode.


1
Bello! Sfortunatamente, sembra che la tua soluzione stia andando nel MODO SBAGLIATO. ;-) Dovrebbe essere una soluzione semplice però. (Modifica: '@Z'(]+32*1=I.)&.(a.&i.)1!:1]1dovresti farlo)
FireFly

Bella cattura, grazie. Sono anche impressionato che tu sia riuscito a correggere il codice da solo: J non è la lingua più immediatamente accessibile là fuori :)
Dan Bron,

Ah, ne ho giocato un po 'con J me stesso .. Sono riuscito a inventarmi u:(a.i.x)+32*1='@Z'I.x=.1!:1]1, che corrisponde alla tua lunghezza ma è molto meno interessante (in quanto non usa' sotto '). A proposito, non sapevo di diadico I., quindi grazie per averlo usato. :-)
FireFly

Freddo. Ma la tua soluzione Befunge ha ancora J beat di 4 personaggi. Ovviamente non posso lasciarlo stare :) Sto provando a vedere se tagliare la soluzione J in basso seguendo il tuo esempio facendo affidamento esclusivamente su "@", anziché su "@" e "Z".
Dan Bron,

(32(23)b.])&.(3&u:), dovrebbe essere più corto di 5 byte.
FrownyFrog,

7

C 64 63 59 55 caratteri

main(c){while(c=getchar(),~c)putchar(c-65u<27?c+32:c);}

Conto solo 63 caratteri lì.
arte

Puoi perdere 9 caratteri: rilascia int e ,c>=0. Non sono necessari qui.
Joe Fish il

abbiamo bisogno di c> = 0 dato che getchar (EOF) sarà <0. Grazie per altri suggerimenti.
Rozuur,

2
1. ~(c=getchar())2.c-64u<27
ugoren

1
Insetto insignificantemente piccolo: sembra che ci dovrebbero essere 65 invece di 64. pastebin.com/Zc9zMx2W
manatwork

5

Golfscript - 17

Programma:

{..64>\91<*32*+}%

Spiegazione:

  1. {}% associa il codice all'interno di ogni carattere nella stringa.
  2. .. copia la parte superiore della pila (il personaggio) due volte.
  3. 64> 1 se il codice carattere è maggiore di 64, altrimenti 0.
  4. \ scambia i due oggetti in pila (ottiene la seconda copia della lettera e memorizza il risultato di 64> nella posizione due).
  5. 91< controlla se il codice carattere è inferiore a 91. Simile al passaggio 3.
  6. *moltiplica i risultati dai passaggi 3 e 5 insieme. Solo uguale a 1, se entrambi i passaggi fossero veri.
  7. 32* moltiplica il risultato del passaggio 6 per 32. Sarà 32 se il passaggio 6 fosse 1, altrimenti 0.
  8. + aggiungi il risultato (32 o 0) sul codice carattere.

Esempio di output:

echo HelLO @ WorLD | ruby golfscript.rb upper_to_lower.gs
hello @ world

4

Perl: 24 caratteri

s/[A-Z]/chr 32+ord$&/ge

Esecuzione di esempio:

bash-4.1$ perl -pe 's/[A-Z]/chr 32+ord$&/ge' <<< 'Hello @ WORLD !'
hello @ world !

Hem, perché chr ord? Sono abbastanza sicuro che non imparerai nulla leggendo la mia risposta ;-)
F. Hauri il

Trucco incredibile, @ F.Hauri!
Manatwork

@ nyuszika7h, +1 è il -pparametro della riga di comando, non una nuova riga.
arte

Oh giusto, scusa.
nyuszika7h

3

Python (33)

In caso di dubbio, utilizzare la shell.

import os;os.system('tr A-Z a-z')

Purtroppo, questo è ancora più lungo della soluzione di Lego.


+1 Questo non è in effetti un Python integrato che stai utilizzando. Funziona solo su Linux, ma comunque molto flessibile !!!

@LegoStormtroopr Funziona ovunque ci sia un trcomando (che fa la cosa giusta) sul percorso della shell invocata, suppongo.
Paŭlo Ebermann,

3

DELPHI

const
  UpChars:set of AnsiChar = ['A'..'Z'];
var
  I: Integer;
begin
  SetLength(Result, Length(pString));
  for I := 1 to length(pstring) do
    Result[i] := AnsiChar((Integer(pString[i] in UpChars))*(Ord(pString[i])+32));
  WriteLn(Result);
end;

3
Questo non è golf. Non pensi che questo pezzo sia molto diverso rispetto agli altri?
Ray

1
@ray Golfing significa ottenere il codice il più breve possibile. Delfi non è un linguaggio eccezionale per giocare a golf. Uso Delphi me stesso e anche se non c'è una grande possibilità di vincere un golf con Delphi, è comunque divertente sfidare te stesso.
Teun Pronk

3

JavaScript - 109 104 (ES6: 95)

Grazie ad alcuni per la versione corretta.

a=prompt();for(b=[i=0];c=a.charCodeAt(i);)b[i++]=String.fromCharCode(c|(c>64&c<91)*32);alert(b.join(""))

Quanto segue funziona se il browser supporta le espressioni di funzione ES6:

alert(prompt().split("").map(c=>String.fromCharCode(c.charCodeAt()|(c>"@"&c<"[")*32)).join(""))

Il primo codice non funziona (testato in FF e Chrome) perché quando si cerca di ottenere un carattere dopo la lunghezza della stringa, si ottiene undefinede quindi c.charCodeAt()fallisce perché non definito non definito charCodeAt. Un esempio funzionante di 105 caratteri:a=prompt();for(b=[i=0];c=a.charCodeAt(i);)b[i++]=String.fromCharCode(c|(c>64&&c‌​<91)*32);alert(b.join(''))
circa il

@some oops, mi chiedo come sia arrivato a quel frammento .. Sono abbastanza sicuro di aver testato quel codice, forse ho copiato una versione non funzionante o qualcosa del genere. Comunque, grazie per la correzione.
FireFly

Usando un bit per bit andanziché uno logico ... bello!
circa il

Un ancora più ES6 soluzione ( 79 ): L=s=>[String.fromCharCode(c.charCodeAt()|(c>"@"&c<"[")*32)for(c of s)].join(''). Utilizzo:L('SoMeTeXt')
Florent,

Bello! Non sono sicuro di renderlo una mera funzione, dal momento che tutte le altre soluzioni sono programmi "adeguati". Comunque, uso molto piacevole di for..ofindipendentemente.
FireFly,

3

Perl 18

s/[A-Z]/$&|" "/eg

Qualcosa di simile a:

perl -pe 's/[A-Z]/$&|" "/eg'  <<<'are NOT allowed to: ToLower() in .NET, strtolower() in PHP'
are not allowed to: tolower() in .net, strtolower() in php

e

perl -pe 's/[A-Z]/$&|" "/eg' <<< "The input string Doesn't cOntaIn...( C0D3-@01F. ;-)"
the input string doesn't contain...( c0d3-@01f. ;-)

Per @FireFly :

perl -pe 's/[A-Z]/$&|" "/eg' <<< "Doesn't this translate @ to \` and [\]^_ to {|}~DEL? "
doesn't ... @ to ` and [\]^_ to {|}~del? 

no.

Più generico: 18 caratteri comunque:

s/[A-Z]/$&|" "/eg

s/[A-Z]/$&^" "/eg

Questo non cambierà nulla nello stato:

perl -pe 's/[A-Z]/$&^" "/eg' <<< "Doesn't ... @ to \` and [\]^_ to {|}~DEL? "
doesn't ... @ to ` and [\]^_ to {|}~del? 

Tutto funziona bene, ma il vantaggio di cambiare |(o) con ^(xor) è che la stessa sintassi potrebbe essere usata per toLower, toUppero swapCase:

toupper:

perl -pe 's/[a-z]/$&^" "/eg' <<< "Doesn't ... @ to \` and [\]^_ to {|}~DEL? "
DOESN'T ... @ TO ` AND [\]^_ TO {|}~DEL? 

e swapCase (18 + 1 = 19 caratteri) :

perl -pe 's/[a-z]/$&^" "/egi' <<< "Doesn't ... @ to \` and [\]^_ to {|}~DEL? "
dOESN'T ... @ TO ` AND [\]^_ TO {|}~del? 

Ho dimenticato +1 per -pscusa @manatwork
F. Hauri

Questo non si traduce @in backtick e [\]^_in {|}~DEL? E qui sta la parte difficile ...
FireFly

1
@FireFly No, $&devono corrispondere [A-Z].
F. Hauri,

Oh mio Dio. Molto bello, allora!
FireFly

3

javascript 80

"X".replace(/[A-Z]/g,function($){return String.fromCharCode($.charCodeAt()+32)})

(76 se rimuovi "X" )

con prompte alert- 92

alert(prompt().replace(/[A-Z]/g,function($){return String.fromCharCode($.charCodeAt()+32)}))

violino

grazie a @FireFly @some @ C5H8NNaO4 e @minitech


Ehm, avresti bisogno di concludere il secondo argomento replacecon function($){return ...}, no? A proposito, il primo parametro della funzione di sostituzione è la stringa corrispondente, quindi è possibile eliminare le parentesi nella regex.
FireFly,

Come potrei fare per eseguirlo, in questo modo?
C5H8NNaO4,

@ C5H8NNaO4 str (codice qui)
Chiller matematico

6
Penso che tutte (o almeno la maggior parte) delle risposte qui contenute leggano da stdin e stampino su stdout. Da quello che raccolgo la convenzione è usare prompte alertper l'I / O in JS.
FireFly

1
È necessaria una /gbandiera affinché funzioni correttamente.
Ry,

2

R

71 caratteri:

chartr(paste(LETTERS,collapse=""),paste(letters,collapse=""),scan(,""))

83 caratteri:

a=as.integer(charToRaw(scan(,"")))
b=a%in%(65:90)
a[b]=a[b]+32
rawToChar(as.raw(a))

Questi sono 86personaggi - le newline contano come 2 caratteri. ( string-functions.com/length.aspx )
Timtech

@Timtech: in R puoi sostituire le nuove righe nel codice in ;modo che non contino solo per un carattere. Potrebbe essere scritto:a=as.integer(charToRaw(scan(,"")));b=a%in%(65:90);a[b]=a[b]+32;rawToChar(as.raw(a))
plannapus il

Sì, ora ho capito. Ho letto su meta ... sembra che solo su Windows le righe siano di 2 caratteri (stavo usando un programma per misurare la lunghezza del mio codice).
Timtech,



2

PHP (42)

Esegui dalla riga di comando:

-R'echo@str_ireplace($a=range(a,z),$a,$argn);'

-R e le virgolette singole non vengono conteggiate.


Se segui la soluzione Peal di Gowtham, conteresti solo 42 caratteri.
eisberg,

1
@eisberg: aggiornato il punteggio, lasciando una versione di 43 caratteri nella cronologia in caso di controversia.
Please Stand

str_ireplacefa una ricerca insensibile alle maiuscole, che allunga le regole, se non le infrange.
ugoren,

@ugoren Non la penso così. Come è chiaramente affermato che non è consentito modificare la funzione solo in caso di modifica del caso e ciò sta ignorando il caso, non modificandolo.
Eisberg,

2

PowerShell: 69 65 64

Ho provato una mezza dozzina di modi per far sì che Replace funzioni nel modo che preferisco senza usare la [regex]::Replacesintassi lunga , ma non ho avuto fortuna. Se qualcun altro ha idea di cosa potrebbe funzionare, per favore, suggeriscilo.

Codice golfizzato:

[regex]::Replace((read-host),"[A-Z]",{[char](32+[char]"$args")})

Modifiche rispetto all'originale:

  • Riorganizzato l'ultimo argomento in modo che [int]non sia più necessario, per suggerimento nei commenti.

Spiegazione:

(read-host) ottiene l'input dell'utente.

[regex]::Replace(... )dice a PowerShell di utilizzare la corrispondenza RegEx per eseguire operazioni di sostituzione su una stringa.

"[A-Z]" corrisponde a tutte le lettere maiuscole.

{... }dice a PowerShell di utilizzare uno script per determinare il valore di sostituzione.

[char]"$args" prende la corrispondenza corrente e la digita come carattere ASCII.

32+ converte il carattere in un numero intero, che rappresenta il codice ASCII, e aumenta il valore di 32, che corrisponderebbe al codice ASCII della lettera minuscola corrispondente.

[char](...) prende il valore risultante e lo converte in un carattere ASCII.

Demo dell'originale:

enter image description here

(Versione corrente testata - screenshot non ancora pubblicato.)


1
Non ho controllato come [regex]::Replace[int]+
aggirarlo

1
In realtà, l'intero ultimo argomento può essere riorganizzato {[char](32+[char]"$args")}, il che elimina la necessità di espressamente lanciare su int e radere via un altro personaggio
gorico

@goric Geez, perché non ci ho già pensato? Sto ancora imparando, immagino.
Iszi,

2

k2, 15 byte

Sono super- tardi per questo, ma ho trovato comunque questo freddo.

{_ci 32+_ic x}'

Anche:

Pyth, 10 byte

Non conta davvero perché Pyth è stato creato dopo che questo è stato pubblicato. Ancora bello.

jkmC+32Cdw

2

05AB1E , 3 byte

u.š

Porta della risposta @ user8777 Python 3 .

Provalo online.

Spiegazione:

u    # Convert the (implicit) input to uppercase
   # Switch the case (upper to lower and vice-versa)
     # (and output the result implicitly)

Ma senza alcun builtin che modifica il caso:

05AB1E , 12 11 byte

ÇIS.u32*+çJ

-1 byte grazie a @Emigna .

Provalo online.

Spiegazione:

Ç            # Get the unicode values of each character of the (implicit) input-String
 IS          # Get the input-string, split to characters again
   .u        # Check for each if it's uppercase or not (1 if truthy; 0 if falsey)
     32*     # Multiply that result by 32 (32 if truhy; 0 if falsey)
        +    # Add it to all the unicode values at the same indices in the list
         ç   # Convert the now modified unicode values back to characters
          J  # And join all characters together to a string again
             # (which is output implicitly as result)

1
ÇIS.u32*+çJsalva un byte nella versione a 12 byte.
Emigna,

@Emigna Ah, intelligente. Avevo provato l' .u32*+approccio in questo modo εÇy.u32*+ç]JçJç
:,

1

Javascript, 105

prompt().split("").map(function(a){c=a.charCodeAt(0);return String.fromCharCode(c|(c-64?32:0))}).join("")

In realtà non è stato specificato alcun modulo di output, quindi eseguilo nella console Sì, JavaScript è davvero dettagliato con charcode <-> stringa


1
c.charCodeAt()- il valore predefinito è 0se un indice viene omesso. Inoltre, interrompe "@" credo (diventa "minuscolo" in backtick)
FireFly

@FireFly Nice, Thanks !, ok lo aggiusterò =)
C5H8NNaO4

1

Rubino: 66

def l(s)s.bytes.map{|b|(65..90).include?(b)?b+32:b}.pack('c*');end

1

C # - 108

class P{static void Main(string[]a){foreach(var c in a[0])System.Console.Write(
(char)(c>64&&c<91?c+32:c));}}

Circa 70 solo per il corpo del metodo.

Aggiungi 5 caratteri per includere un LF / CR nell'output:

class P{static void Main(string[]a){foreach(var c in a[0]+"\n")System.Console.Write(
(char)(c>64&&c<91?c+32:c));}}

Una versione LINQ sarebbe più breve:

class P{static void Main(string[]a){a[0].Any(c=>System.Console.Write(
(char)(c>64&&c<91?32+c:c))is P);}}

(103) .. tranne che richiede using System.Linq;(totale: 121).


1

Haskell - 58

p x|(elem x['A'..'Z'])=[x..]!!32|1<2=x
main=interact$map p

1

Python 3 - 70

Updated for OP's changes.

I'm a Python newbie, so any critique is welcome.

print("".join(chr(ord(c)+32) if 64<ord(c)<91 else c for c in input()))

I'm sorry, I had to say that you're not allowed to use a to-lower function on one character. Question updated.
ProgramFOX

1
Please see my recent comment: your code does only work if the input string contains only uppercase characters, but please note that it also contain other ASCII characters such as lowercase characters and numbers.
ProgramFOX

Okay, will update when I get home
asteri

@ProgramFOX Updated.
asteri

Jeff, check out @minitechs answer. You both have very similar approaches so you should be able to see how, and why his answer is shorter.

1

Perl, 9 + 1 (for -p flag) = 10

$_="\L$_"

\L was specifically asked about and allowed, because even though it's a built-in, it's not a function.


1

Powershell, 53 49 bytes

-4 bytes thanks @AdmBorkBork

-join($args|% t*y|%{[char](32*($_-in65..90)+$_)})

Test script:

$f = {

-join($args|% t*y|%{[char](32*($_-in65..90)+$_)})

}

@(
    ,("Hello WORLD from PowerShell", "hello world from powershell")
) | % {
    $a,$e = $_
    $r = &$f $a
    "$($r-eq$e): $r"
}

Output:

True: hello world from powershell

cool! ¯\_(ツ)_/¯
mazzy

1

8086 machine code, 14 bytes

Assembled:

AC 3C 41 7C 06 3C 5A 7F 02 0C 20 AA E2 F2

Unassembled listing:

 ; Lowercase a string
 ; Input: string: SI, length: CX
 ; Output: string: DI
 TOLOW  MACRO   
        LOCAL _LOOP, _STORE
       _LOOP:
 AC         LODSB           ; load byte from [SI] into AL, advance SI 
 3C 41      CMP  AL, 'A'    ; is char less than 'A'? 
 7C 06      JL   _STORE     ; if so, do not convert 
 3C 5A      CMP  AL, 'Z'    ; is char greater than 'Z'? 
 7F 02      JG   _STORE     ; if so, do not convert 
 0C 20      OR   AL, 020H   ; lowercase the char 
       _STORE:
 AA         STOSB           ; store char to [DI], advance DI 
 E2 F2      LOOP _LOOP      ; continue loop through string 

Implemented as a MACRO (essentially a function). Input string in SI, length in CX. Output string in DI.

Output from PC DOS test program:

enter image description here

Download and test TOLOW.COM example program.


where is the 14 byte count coming from? the snippet is longer than that, even without comments... is 14 bytes the compiled program?
Jonah

1
@Jonah The byte opcode is in the lefthand column, AC 3C 41, etc. I'll add the assembled hex byte code to the top for clarity. codegolf.meta.stackexchange.com/a/12340/84624
640KB
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.