# Let's learn some soil pH chemistry!

Andrew is a chemist, interested in the acidity of solutions and in agriculture. After months of research (Google is not his friend), he came up with the following table* regarding the human-readable level of acidity in terms of the pH (potential of Hydrogen):

         Denomination        |         pH range
|
-------------------------+-----------------------------
Ultra acidic             |          below 3.5
-------------------------+------------------------------
Extremely acidic         |    between 3.5 and 4.4
-------------------------+------------------------------
Very strongly acidic     |    between 4.5 and 5.0
-------------------------+------------------------------
Strongly acidic          |    between 5.1 and 5.5
-------------------------+------------------------------
Moderately acidic        |    between 5.6 and 6.0
-------------------------+------------------------------
Slightly acidic          |    between 6.1 and 6.5
-------------------------+------------------------------
Neutral                  |    between 6.6 and 7.3
-------------------------+------------------------------
Slightly alkaline        |    between 7.4 and 7.8
-------------------------+------------------------------
Moderately alkaline      |    between 7.9 and 8.4
-------------------------+------------------------------
Strongly alkaline        |    between 8.5 and 9.0
-------------------------+------------------------------
Very strongly alkaline   |          over 9.0


Given a non-negative decimal number representing the pH of a substance, output its Denomination. You can take input and provide output by any standard method. The data types you are allowed to take input with are:

• Float
• Double
• Your language's standard decimal number data type
• String

And you must output a String representing the denomination. Built-ins related to chemistry are forbidden (Sorry, Mathematica!).

Approximation Rule: If the pH you receive is between an upper bound of a denomination and the lower bound of the next one (e.g. between 7.8 and 7.9), it gets approximated to the closest value between the two: if the pH ≥ upperBound of the first + 0.5, then it should receive the second denomination, but if the pH < upperBound of the first + 0.5, then it should receive the first one (e.g 7.85 is approximated to 7.9, but 7.84999 is approximated to 7.8). See the test cases for clarifications.

# Test Cases:

Input ->  Output

6.40  ->  Slightly acidic
8.399 ->  Moderately alkaline
3.876 ->  Extremely acidic
10.60 ->  Very strongly alkaline
0.012 ->  Ultra acidic
7.30  ->  Neutral
7.85  ->  Moderately alkaline (the approximation rule is applied)
7.849 ->  Slightly alkaline (the approximation rule is applied)
6.55  ->  Neutral (the approximation rule is applied)


This is , so the shortest valid submission (in bytes) wins!

*Andrew did not come up with that, it was Wikipedia!

• Sandbox for those who can see deleted posts. – Mr. Xcoder Jun 19 '17 at 10:17
• yeah this doesn't really work with actual acidity levels. anything more acidic than lemon juice is ultra acidic – Destructible Lemon Jun 19 '17 at 10:22
• @DestructibleLemon If lemon juice is Ultra acidic, then Fluoroantimonic acid, that behaves like having −31.3 is a total atomic bomb :)) – Mr. Xcoder Jun 19 '17 at 10:26
• oh, I see where you went wrong. 3.5 ph is not ultra acidic, but it is ultra acidic if the soil you are growing plants in is 3.5 ph. what I mean is, this table refers to soil ph – Destructible Lemon Jun 19 '17 at 10:46
• Brownie points for an answer in Python or Swift :) – Mr. Xcoder Jun 19 '17 at 12:25

# Jelly,  77 73  71 bytes

“£RĿÐƭðṚ°ƲṂṾẒ=ʂXḣsịɠ<»Ḳµ,Ṛ;€"“¡D⁺“a&»j“¿<z»W¤ṙ3
×20<“FYeoy³ƓɗʋṆ‘Sị¢⁾. y


A monadic link taking the number and returning a list of characters; or a full program printing the result.

Try it online!

### How?

“ ... »Ḳµ,Ṛ;€"“¡D⁺“a&»j“¿<z»W¤ṙ3 - Link 1, name list: no arguments
“ ... »                          - compression of "Ultra Extremely Very.strongly Strongly Moderately Slightly"
Ḳ                         - split at spaces
,                       - pair these two lists
“¡D⁺“a&»           - compression of [" alkaline"," acidic"]
"                   - zip with:
;€                    -   concatenate for €ach
“¿<z»     -   compression of "Neutral"
W    -   wrap in a list
j          - join
ṙ3 - rotate left by 3: ["Strongly alkaline","Moderately alkaline","Slightly alkaline","Neutral","Slightly acidic","Moderately acidic","Strongly acidic","Very.strongly acidic","Extremely acidic","Ultra acidic","Ultra alkaline","Extremely alkaline","Very.strongly alkaline"]

×20<“FYeoy³ƓɗʋṆ‘Sị¢⁾. y - Main link: number, pH
×20                     - multiply by 20
“FYeqy³ƓɗʋṆ‘        - code-page indexes = [70,89,101,111,121,131,147,157,169,180]
<                    - less than? (vectorises)
-   i.e.: pH < [3.5,4.45,5.05,5.55,6.05,6.55,7.35,7.85,8.45,9]
S       - sum
ị      - index into (1-indexed and modular)
- ...note that the sum is never 11 or 12, so "Ultra alkaline" and
-    "Extremely alkaline" wont be fetched, but that a sum of 0
-    fetches "Very.strongly alkaline", as required.
⁾.   - literal list of characters ['.', ' ']
y - translate (replace any '.' with a ' ' i.e. for "Very.strongly")
- if running as a full program, implicit print

• I always enjoy competition between 05AB1E and Jelly... Only 2 bytes away – Mr. Xcoder Jun 19 '17 at 11:42
• Jelly beats 05AB1E?!?! – Erik the Outgolfer Jun 19 '17 at 11:43

foreach([35,9.5,6,5,5,5,8,5,6,5.5]as$l)$p+=$argn*10>=$s+=$l;$p-=$argn==9;echo[Ultra,Extremely,"Very strongly",Strongly,Moderately,Slightly][$p>6?12-$p:$p],[" acidic",Neutral," alkaline"][1+($p<=>6)];  Try it online! # C# (.NET Core), 236 bytes p=>{var l=new[]{70,89,101,111,121,131,147,157,169,180,280};var a="Ultra,Extremely,Very strongly,Strongly,Moderately,Slighty, acidic,Neutral, alkaline".Split(',');int i=0;for(;p*20>=l[i];i++);return i==6?a[7]:i<6?a[i]+a[6]:a[12-i]+a[8];}  Try it online! This solution considers that p cannot be greater than 14. # T-SQL, 305 299 bytes DECLARE @ char(999)=REPLACE(REPLACE(REPLACE(REPLACE('SELECT TOP 1i FROM(VALUES(''Very s$#9&S$#8.4&Moderately#7.8&Slightly#7.3&Neutral'',6.5&Slightly@6&Moderately@5.5&S$@5&Very s$@4.4&Extremely@3.4&Ultra@-1))x(i,j),t WHERE j<a','#',' alkaline'','),'@',' acidic'','),'&','),('''),'$','trongly')EXEC(@)


Input is via a pre-existing table t with DECIMAL(4,1) column a, per our Input/Output rules.

Because of the DECIMAL(4,1) data type, any "approximation rule" rounding takes place when the value is entered into the input table, so doesn't need to be explicitly managed by my code.

After the space-saving REPLACES are performed, this is a simple SQL query joining our input table with our list of values:

SELECT TOP 1 i
FROM(VALUES
('Very strongly alkaline',9),
('Strongly alkaline',8.4),
('Moderately alkaline',7.8),
('Slightly alkaline',7.3),
('Neutral',6.5),
('Slightly acidic',6),
('Moderately acidic',5.5),
('Strongly acidic',5),
('Very strongly acidic',4.4),
('Extremely acidic',3.4),
('Ultra acidic',-1)
) x(i,j), t
WHERE j<a


I reverse the order so TOP 1 picks the first one less than our input value.

Even this form (after removing line breaks and extra spaces) is pretty good, at 318 bytes. Adding the overhead of the DECLARE, REPLACES AND EXEC only becomes worth it with all the repeated phrases.

EDIT: Save 6 bytes by removing unnecessary ".0" on several values

# 05AB1E, 8180797776 74 bytes

'Äˆ“¢³¿™ly³¾‚Òw““³¾§ÓªÅ“«#Â¦¦’šÉaƒ£’«Š’w¡Îic’«)˜™'wð:I•t{~À•ST+.¥70+20/‹Oè


Try it online!

Test suite

Explanation

'Äˆ                   # push the string "neutral"
“¢³¿™ly³¾‚Òw“         # push the string "slightly moderately strongly veryw"
“³¾§ÓªÅ“              # push the string "strongly extremely ultra"
«                     # concatenate the top 2 items on the stack
#                    # split on spaces
Â                   # push a reversed copy
¦¦                 # remove the first 2 elements of the copy ("ultra", "extremely")
’šÉaƒ£’«              # append the string "walkaline" to each ("walk"+"a"+"line")
Š             # move down 2 places on the stack
’w¡Îic’«              # append the string "wacidic" to each ("w"+"acid"+"ic")
)˜            # wrap stack in a list and flatten
™           # title case each
'wð:       # replace each instance of "w" with a space
I                     # push input
•t{~À•               # push the base 255 compressed number 920006021
ST+            # split to list of digits and add 10 to each
.¥          # undelta (compute increments from 0)
70+       # add 70 to each
20/    # divide each by 20
‹   # compute input less than for each
O  # sum
è # use this to index into list of strings

• This is surprisingly long for 05AB1E – Mr. Xcoder Jun 19 '17 at 11:11
• Late to the party, but still curious: does anyone directly program in this language (even if only for code golfing) or is this the output of some sort of a "compiler" ? – avl42 Jun 20 '17 at 7:52
• @avl42: We code directly in this language yes (generally only for golfing of course). I'd hate to see someone use this in production code ;) It is an interpreted language so code you write in this language gets interpreted to python code. – Emigna Jun 20 '17 at 8:24
• @Emigna I'd say "translated" rather than "interpreted" (it's kind of opposite meaning) – anatolyg Jun 20 '17 at 9:44
• @anatolyg: Yes, you are correct there. I always think interpreted for some reason, probably due to python. It is translated into an interpreted language :) – Emigna Jun 20 '17 at 9:48

# Retina, 228 bytes

$.00 \.(.)\.?(.).*$1$2 .+$*
1{900,}
VA
1{845,}
STA
1{785,}
MA
1{735,}
SLA
1{655,}
Neutral
1$1 acidic 1{605,} SL 1{555,} M 1{505,} ST 1{445,} V 1{350,} Extremely 1+ Ultra M Moderately V Very sT T trongly L lightly A alkaline  Try it online! Link includes test suite. Explanation: $
.00
\.(.)\.?(.).*
$1$2


Multiply the input by 100 by suffixing a spare decimal point and two zeros then deleting the decimal point and all but two digits after it.

.+
$*  Convert to unary. 1{900,} VA 1{845,} STA 1{785,} MA 1{735,} SLA  Handle all the alkalis, converting into abbreviations that will be expanded later. 1{655,} Neutral  Handle neutral. 1$
1 acidic


Anything left must be acidic. (But leave the 1 in case the pH is 0.001)

1{605,}
SL
1{555,}
M
1{505,}
ST
1{445,}
V
1{350,}
Extremely
1+
Ultra


Handle all the acids.

M
Moderately
V
Very sT
T
trongly
L
lightly
A
alkaline


Expand the abbreviations.

• Wow, I think it took a while to golf it down... – Mr. Xcoder Jun 19 '17 at 12:53

# Python 2, 202 bytes

-15 bytes thanks to @JonathanAllan

lambda k:'Neutral_Slightly_Moderately_Strongly_Very strongly_Extremely_Ultra'.split('_')[abs(sum(round(k*10)>ord(i)for i in'",27<AINT')+(k>9)-(3.45<k<3.5)-6)]+(' acidic'*(k<6.55)or' alkaline'*(k>=7.35))


Try it online!

• You took my brownie points. – Mr. Xcoder Jun 19 '17 at 14:13

## JavaScript (ES6), 192189185 184 bytes

k=>([...'09544474540'].some(n=>(i--,k-=++n)<0,i=7,k=k*10-33.5),'Neutral,Slightly,Moderately,Strongly,Very strongly,Extremely,Ultra'.split,[i<0?-i:i]+(i?i>0?' acidic':' alkaline':''))


### Test cases

let f =

k=>([...'09544474540'].some(n=>(i--,k-=++n)<0,i=7,k=k*10-33.5),'Neutral,Slightly,Moderately,Strongly,Very strongly,Extremely,Ultra'.split,[i<0?-i:i]+(i?i>0?' acidic':' alkaline':''))

console.log(f(6.40))  //  Slightly acidic
console.log(f(8.399)) //  Moderately alkaline
console.log(f(3.876)) //  Extremely acidic
console.log(f(10.60)) //  Very strongly alkaline
console.log(f(0.012)) //  Ultra acidic
console.log(f(7.30))  //  Neutral
console.log(f(7.85))  //  Moderately alkaline
console.log(f(7.849)) //  Slightly alkaline
console.log(f(6.55))  //  Neutral

# Excel, 240 bytes

=CHOOSE((A1<6.55)+(A1<6.05)+(A1<5.55)+(A1<5.05)+(A1<4.45)+(A1<3.5)+(A1>=7.35)+(A1>=7.85)+(A1>=8.45)+(A1>9)+1,"Neutral","Slightly","Moderately","Strongly","Very Strongly","Extremely","Ultra")&IF(A1<6.55," acidic",IF(A1>=7.35," alkaline",""))


## Javascript, 222 209 bytes

x=>'Very strongly,Strongly,Moderately,Slightly,Neutral,Extremely,Ultra'.split(',',7,x-=0.049)[x>9?0:x>8.4?1:x>7.8?2:x>7.3?3:x>6.5?4:x>6?3:x>5.5?2:x>5?1:x>4.4?0:x>3.5?5:6]+(x<6.5?' acidic':x>7.3?' alkaline':'')


Still golfing it a little

var f = x=>'Very strongly,Strongly,Moderately,Slightly,Neutral,Extremely,Ultra'.split(',',7,x-=0.049)[x>9?0:x>8.4?1:x>7.8?2:x>7.3?3:x>6.5?4:x>6?3:x>5.5?2:x>5?1:x>4.4?0:x>3.5?5:6]+(x<6.5?' acidic':x>7.3?' alkaline':'')

console.log(f(6.40));
console.log(f(8.399));
console.log(f(3.876));
console.log(f(10.60));
console.log(f(0.012));
console.log(f(7.30));
console.log(f(7.85));
console.log(f(7.849));
console.log(f(6.55));

• I don't think you need to assign the function to a variable. – Zacharý Jun 19 '17 at 15:18