# Ungolf the Wind

Weather conditions at airports are reported to pilots in METAR (METeorological Aerodrome Report) format. This format could be described as being "golfed." Here are some examples:

METAR KPDX 241653Z 16003KT 1/4SM R10R/4500VP6000FT FG SCT000 01/M01 A3040 RMK AO2 SLP293 FG SCT000 T00061006 $METAR PAMR 241753Z 00000KT 10SM OVC080 00/M02 A2985 RMK AO2 SLP111 T00001017 10022 21006 55003 METAR KLAX 241653Z VRB05KT 10SM FEW030 SCT060 17/11 A2992 RMK AO2 SLP130 T01720106 METAR KBOS 241754Z 27012G19KT 10SM FEW045 SCT250 09/M05 A3000 RMK AO2 SLP158 T00941050 10094 20044 56020  These are all American METARs, which is all your program needs to accept. The international format is slightly different. You only need the wind component, which is after the third space. METAR KLAX 241653Z | VRB05KT | 10SM FEW030 SCT060 17/11 A2992 RMK AO2 SLP130 T01720106 Things that don't matter | *Wind* | More things that don't matter  However, your program will be given the entire METAR. Let's take the METAR from KPDX as the first example. Its wind component is 16003KT. When the code looks like this, it's simply indicating the wind direction and speed. The first three digits, 160, are the direction in degrees; the last two, 03, are the speed in knots (KT; a knot is a nautical mile per hour). In this case, the output should clearly indicate the direction and speed as separate values. You do not have to indicate units. When there is no wind, it will look like the PAMR METAR: 00000KT. This indicates zero knots; zero degrees is used as a placeholder, because there is, of course, no way to measure wind direction without wind. Just parse these the same as regular codes; your program does not have to treat this as a special case. Sometimes, as was the case at KLAX at the time of writing, the wind direction is variable. This is encoded as VRB05KT. The direction is replaced with VRB, which your program must parse, and the speed is encoded normally. Wind with gusts is encoded like this: 27012G19KT. The 270 indicates the direction. The 12 indicates that the average wind speed is 12 knots, while G19 indicates that gusts are reaching 19 knots. I did not find a current METAR that actually had this, but your program must also handle variable winds with gusts, which would look like this: VRB12G19KT. Your program must return or output three numbers. The first is the wind direction in degrees, or -1 if the wind is VRB. The second is the wind speed. The third is the gust speed if there are gusts, or -1 otherwise. Leading zeros are not allowed. Here are some test cases. They are the four real METARs from the start of the question, plus a constructed one to test for variable gusty winds. METAR KPDX 241653Z 16003KT 1/4SM R10R/4500VP6000FT FG SCT000 01/M01 A3040 RMK AO2 SLP293 FG SCT000 T00061006$
160 3 -1

METAR PAMR 241753Z 00000KT 10SM OVC080 00/M02 A2985 RMK AO2 SLP111 T00001017 10022 21006 55003
0 0 -1

METAR KLAX 241653Z VRB05KT 10SM FEW030 SCT060 17/11 A2992 RMK AO2 SLP130 T01720106
-1 5 -1

METAR KBOS 241754Z 27012G19KT 10SM FEW045 SCT250 09/M05 A3000 RMK AO2 SLP158 T00941050 10094 20044 56020
270 12 19

METAR KTVG 241754Z VRB12G19KT 10SM FEW045 SCT250 09/M05 A3000 RMK AO2 SLP158 T00941050 10094 20044 56020
-1 12 19

• Does the wind component always start at the same point? It does in all of the examples. (If so it may be possible to save bytes over methods splitting by spaces.) Commented Dec 3, 2023 at 17:59
• @JonathanAllan yes, it will always be at the same point. The first word is always METAR or SPECI, the airport code is always four characters, and the date/time code is always seven. Commented Dec 3, 2023 at 18:11
• Might want to include an example where the airport code includes "KT" just to see if anyone is keying off those letters incorrectly. Commented Dec 4, 2023 at 18:36
• @Xcali good idea! I changed the last one to "KTVG," since it was made up anyway. Thank you for the suggestion! Commented Dec 4, 2023 at 19:11

={iferror(--mid(A1,20,3),-1),mid(A1,23,2),ifna(--regexextract(A1,"G(\d\d)"),-1)}


Put the input in cell A1 and the formula in B1. Output in cells B1:D1.

Simple text manipulation in an { array expression }.

# Charcoal, 1716 15 bytes

…ＩＥ⪪ε³⁻Σ⁺ψι›ια³


Try it online! Link is to verbose version of code. Explanation:

    ε           Fourth word of input
⪪ ³          Split into groups of three characters
Ｅ             Map over groups
ψ      Null byte
⁺       Concatenated with
ι     Current group
Σ        Extract embedded integer
⁻         Minus
ι   Current group
›     Is greater than
α   Predefined variable uppercase alphabet
Ｉ              Cast to string
…              ³ Take the first three
Implicitly print


In practice -1 is only needed for VRB and T so comparing to any string between 99 and T would work.

# Jelly, 18 15 bytes

Ḳ4ịs3ḣ3f€ØDȯ€-V


Try it online!

A monadic link taking a METAR-formatted string and returning a list of integers. (Has the side effect of sometimes outputting some zeros to STDOUT which is permitted as per this meta post.)

Thanks to @JonathanAlkan for saving three bytes!

## Explanation

Ḳ                   | Split at spaces
4ị                 | 4th sublist
s3               | Split into pieces of length 3
ḣ3             | First three
f€ØD         | Keep only digits
ȯ€-      | Replace blanks with -1
V     | Interpret as Jelly code


• fØDV€ȯɗ€- saves one Commented Dec 3, 2023 at 0:36
• Ḳ4ịs3ḣ3f€ØDȯ€-V works as a monadic Link yielding the desired triple of integers with the side effect of potentially printing some zeros. Most relevant meta I could find, maybe there is a better one though. Commented Dec 3, 2023 at 14:49
• @JonathanAllan thanks, I’d forgotten it was ok to output some unneeded content to STDOUT while returning the result from a function (or link). I’d previously rejected a solution similar to this because of the extra zeros, but have gone with this now. Commented Dec 3, 2023 at 19:40

# Retina 0.8.2, 39 bytes

4=M!\w+
3M!.{1,3}
%(\D

^0+\B

^$-1  Try it online! Outputs the values on separate lines but link is to test suite that joins on commas for convenience. Explanation: 4=M!\w+  Extract the fourth word. 3M!.{1,3}  Split it into three triplets. 3G  Keep only three. %(  Apply the remainder of the script to each line independently. \D  Delete non-digits. ^0+\B  Delete leading zeros. ^$
-1


Insert -1 on empty lines.

# JavaScript, 54 45 bytes

s=>[19,22,25].map(x=>~(-1-s.substr(x,x/7^1)))


Try it online!

−9 by using indices directly in the input string and the (deprecated) String.prototype.substr method.

• [19,22,25].map(…): Produce an array of the results of calling the function inside with argument 19, 22, and 25.
• s.substr(x,x/7^1): Take the substring starting at index x, of length 3 for x=19, or length 2 for the other values of x. This extracts the digits that make up the desired values; in the absence of a number, the substring is VRB from x=19 or T  from x=25.
• (-1-…): Subtract it from −1, implicitly performing numeric coercion. If the string does not express a number, it becomes NaN, and the subtraction produces NaN.
• ~…: Bitwise NOT. This reproduces the original number, while NaN becomes 0 when converted to a 32-bit integer, and then the bitwise NOT of 0 is −1.

# 05AB1E, 13 bytes

#3è3ô3£εþ®s‚à


Explanation:

#             # Split the (implicit) input-string on spaces
3è           # Pop and keep the (0-based) 3rd item (aka the fourth item)
3ô         # Pop and split this substring into parts of size 3
3£       # Pop and only keep the first three parts
ε      # Map over this triplet of parts:
þ     #  Only keep the digits of the current string-part
®s‚  #  Pair it with a leading -1 (push -1; swap; pair top two)
à #  Pop and push the maximum of this pair, which serves two purposes:
#  1. It will convert the values in the pair to integers to determine the
#     max, removing the leading 0s from the digit-strings
#  2. It will take the first item if the pair contains a non-number, hence
#     the need for the swap s when pairing it to the empty string
# (after which the resulting triplet of integers is output implicitly)


# sed -E, 81 75 bytes

-6 bytes thanks to @Jordan

s/.{19}(...)(..)(G(..))?.*/ \1 \2 \4/;s/ VRB| $/ -1/g;s/ 0*(\w)/ \1/g;s/ //  Attempt This Online! • You can replace (\w+){3} with .{19} (and then adjust the subsequent capture group numbers) for -4 bytes. You can also replace [^ ] with \w for -2 bytes. I'd also argue you can omit the last substitution (s/ //) but that may be debatable. Commented Dec 4, 2023 at 16:54 # Uiua 0.4.1, 80 bytes ⊐∵parse≡(⊂⊂∩□⊃((∘|"¯1")≍"VRB"⊔.↙3|⊃↙(□↘+1)⊗@G.(⊂:"G¯1"|∘)∊@G.↙-2⧻.↘3)⊔⊡3⊜□≠@ .⊔)  See it in action # Python3, 104 bytes lambda s:((-1 if'VRB'in(s:=s.split()[3])else s[:3]),s[3:5],s[(i:=s.index('G'))+1:i+3]if'G'in s else -1)  Try it online! Another approach (much shorter and nicer): # Python3, 83 bytes Thanks to Jonathan! lambda s:[int(''.join(c for c in s.split()[3][i:i+3]if':'>c)or'-1')for i in(0,3,6)]  Try it online! • @JonathanAllan Thanks for pointing that. I'll change it. Commented Dec 3, 2023 at 17:19 • It does have to remove leading 0s. I think you can save one byte, though, by removing the space in else -1. Commented Dec 3, 2023 at 17:31 • @JonathanAllan That's very bright solution, why don't you submit as an answer yourself? Commented Dec 3, 2023 at 17:58 • @JonathanAllan Thanks! I added it to my answer. Commented Dec 3, 2023 at 18:11 • You can get to 75 chars with lambda s:[int(''.join(c for c in s[19+i:22+i]if':'>c)or -1)for i in(0,3,6)] Commented Dec 4, 2023 at 3:46 # Perl 5-n, 59 bytes / (...)(..)G?(..)?KT/;say for$1eq VRB?-1:$1*1,$2*1,\$3*1||-1


Try it online!

# sclin, 33 bytes

w<>3:3/3tk"\D"""\ /#1_.||# map N


Try it on scline!

## Explanation

Prettified code:

w<> 3: 3/ 3tk  .. get 4th word, chunk by 3s, take 3
"\D"""\ /#      .. (vectorized) remove non-digits
1_.||# map      .. replace empty (falsy) with -1
N               .. (vectorized) convert to number
`