How fast am I vrooooming?

19

1

Introduction

My car speedometer was hacked! Instead of showing me how fast i'm driving, it just shows: "Vroooom!" Please help me know how fast i'm going.

Challenge

Take a string as input, and check if it matches the regex /^[Vv]ro*m!$/m. In English that means any line of the string must start with a capital or lowercase v, then a lowercase r, then any amount (including zero) of the lowercase letter o, then the exact string m!. There may be other lines, but the Vroom string must be on it's own line.

If you find a match, then you must count the amount of o's in the Vroom string and output it. If you don't find a match however, you should output any default value that can't be outputted otherwise (like -1 or an empty string)

Reminders

Scoring

This is , so the shortest code in bytes wins. However, I will not mark any answer as accepted.

Test cases

Input

Vrom!

Output 1

Input

vrooooooom!

Output 7

Input

Hello, Vroom!

Output (none)

Input

Foo bar boo baz
Vrooom!
hi

Output 3

Input

Vrm!ooo

Output (none)

Input

PPCG puzzlers pie

Output (none)

Input

hallo
vROOOm!

Output (none)

FireCubez

Posted 2018-11-02T18:29:09.540

Reputation: 857

Answers

9

sed 4.2.2, 20 bytes

-nr options required at the command-line.

s/^[Vv]r(o*)m!$/\1/p

This outputs the speed in unary as the number of os.

Try it online!

Digital Trauma

Posted 2018-11-02T18:29:09.540

Reputation: 64 644

Can't tell Vrm! from Vram! – l4m2 – 2018-11-03T08:56:01.417

4

Python 2, 56 53 bytes

lambda x:len(re.search('^[Vv]r(o*)m!$',x,8).group(1))

Try it online!

Basic regex and grouping, uses re.MULTILINE flag (which has a value of 8) and re.search to ensure it works for multiline inputs. Raises an exception when no match is found. Thanks to @ovs for the -3 bytes from (re.M == 8) tip.

Shamtam

Posted 2018-11-02T18:29:09.540

Reputation: 141

1

Welcome to PPCG! I reformatted your answer to make it appear a bit nicer, if you're unhappy with my edit you can always roll back. Btw. I suggest to link to something like tio.run such that people can easily test your answer.

– ბიმო – 2018-11-02T20:30:09.497

re.M has the value 8, so can just use re.search(regex,x,8) – ovs – 2018-11-03T16:24:46.903

4

R, 62 60 58 44 bytes

nchar(grep("^[Vv]ro*m!$",readLines(),v=T))-4

Try it online!

@Giuseppe with 14 bytes golfed.

Original approach with explanation:

function(x)attr(el(regexec("(?m)[Vv]r(o*)m!$",x,,T)),"m")[2]

Try it online!

R has seven pattern matching functions. The more commonly used ones are grep, grepl, and sub, but here's a nice use for regexec.

regexec gives you a bunch of things, one of which is the length of any captured substring, in this case the (o*) part of the multiline regex.

The attr(el .... "m")[2] stuff is a golfy way to get the desired number.

Returns NA if there is no match.

ngm

Posted 2018-11-02T18:29:09.540

Reputation: 3 974

58 bytes with a different approach – digEmAll – 2018-11-03T15:33:27.833

I have a 44 byte approach... Not gonna post it unless you want me to. – Giuseppe – 2018-11-04T01:53:29.490

@Giuseppe not sure why not? Especially if it's fundamentally different. – ngm – 2018-11-04T02:01:57.783

3

JavaScript (Node.js), 41 bytes

a=>(l=/[Vv]r(o*)m!/.exec(a))&&l[1].length

Try it online!

Luis felipe De jesus Munoz

Posted 2018-11-02T18:29:09.540

Reputation: 9 639

This fails for vroooooooooooom!x\nvrom! – ბიმო – 2018-11-02T20:27:06.670

1

Seeing as we're allowed exit with an error if no match is found, you could do this for -3 bytes, fixing the problem @BMO mentioned above in the process.

– Shaggy – 2018-11-02T22:32:57.570

Uncrossed-out 41 is definitely still 41 – Redwolf Programs – 2018-11-03T02:13:57.607

@Shaggy What's the space in [1]. length for? – l4m2 – 2018-11-03T08:58:02.427

@l4m2, a typo! I didn't spot it on my phone 'cause length was breaking to a newline anyway. – Shaggy – 2018-11-03T10:53:05.950

3

Powershell, 62 58 53 48 bytes bytes

"$($args|sls '(?m-i)^[Vv]ro*m!$'|% M*)".Length-4

returns numbers of o in a first Vroom!, or -4 if Vroom! not found.

Notes:

  • sls is alias for Select-String;
  • (?m-i) inside regexp means:
    • Use multiline mode. ^ and $ match the beginning and end of a line, instead of the beginning and end of a string.
    • Use case-sensitive matching
  • |% M* is shortcut for the property Matches, which gives a first match because we don't use -AllMatches parameter.

Test script:

$f = {

"$($args|sls '(?m-i)^[Vv]ro*m!$'|% M*)".Length-4

}

@(
,('Vrom!',1)
,('vrooooooom!',7)
,('Hello, Vroom!',-4)
,('Foo bar boo baz
Vrooom!
hi',3)
,('Vrm!ooo',-4)
,('PPCG puzzlers pie',-4)
,('hallo
vROOOm!',-4)
,('
Vrooom!
Vrooooom!
',3)        # undefined behavior.
,('vrm!',0) # :)
) | % {
    $n,$expected = $_
    $result = &$f $n
    "$($result-eq$expected): $result"
}

Output:

True: 1
True: 7
True: -4
True: 3
True: -4
True: -4
True: -4
True: 3
True: 0

mazzy

Posted 2018-11-02T18:29:09.540

Reputation: 4 832

2

SNOBOL4 (CSNOBOL4), 99 82 bytes

I	INPUT POS(0) ('V' | 'v') 'r' ARBNO('o') @X 'm!' RPOS(0)	:F(I)
	OUTPUT =X - 2
END

Try it online!

Pretty direct SNOBOL translation of the spec, reads each line until it finds one that matches ^[Vv]ro*m!$, then outputs the length of the o* bit.

Enters an infinite loop if no Vroom! can be found.

Giuseppe

Posted 2018-11-02T18:29:09.540

Reputation: 21 077

Is all that whitespace necessary? Wow. – FireCubez – 2018-11-02T18:51:43.453

5@FireCubez yep, that's what you get with a 50+ year-old language: weird whitespace requirements. It uses space/tab as concatenation and you must surround operators with whitespace as well. – Giuseppe – 2018-11-02T18:53:34.607

2

PowerShell, 83 bytes

($args-split"`n"|%{if(($x=[regex]::Match($_,"^[Vv]ro*m!$")).success){$x}}).length-4

Try it online!

-splits the input $args on `newlines, pipes those into a for loop. Each iteration, we check whether our [regex]::Match is a .success or not. If so, we leave $x (the regex results object) on the pipeline. Outside the loop, we take the .length property -- if it's the regex results object, this is the length of the match (e.g., "Vroom!" would be 6); if it's not a regex results object, the length is zero. We then subtract 4 to remove the counts for the Vrm! and leave that on the pipeline. Output is implicit. Outputs a -4 if no match is found.

AdmBorkBork

Posted 2018-11-02T18:29:09.540

Reputation: 41 581

sls "^[Vv]ro*m!$"? – mazzy – 2018-11-02T18:58:39.200

@mazzy How would that work for multiline input? Your only input is one string, and so sls will give back ('','Vroom!','') for example. – AdmBorkBork – 2018-11-02T19:06:41.357

it's not completed solution. I mean, you can try sls instead [regex]::Match – mazzy – 2018-11-02T19:08:54.463

@mazzy Maybe you should post it as a separate solution. – AdmBorkBork – 2018-11-02T19:13:05.580

2

Retina, 21 bytes

L$m`^[Vv]r(o*)m!$
$.1

Try it online! Explanation: L lists matches, so if the regex fails to match then output is empty. $ causes the result to be the substitution rather than the match. m makes it a multiline match (the equivalent to the trailing m in the question). The . in the substitution makes it output the length of the capture in decimal.

Neil

Posted 2018-11-02T18:29:09.540

Reputation: 95 035

2

Perl 6, 26 bytes

{-!/^^[V|v]r(o)*m\!$$/+$0}

Try it online!

nwellnhof

Posted 2018-11-02T18:29:09.540

Reputation: 10 037

2

C (gcc), 188 183 bytes

Why use regexes when you can use a state machine instead? :-)

a,b;f(char*s){for(a=b=0;a<5;s++){!a&*s==86|*s=='v'?a++:a==1&*s=='r'?a++:a==2?*s-'o'?*s-'m'?0:a++:b++:a==3&*s==33?a++:!*s&a==4?a++:*s-10?(a=-1):a-4?(a=0):a++;if(!*s)break;}s=a<5?-1:b;}

Try it online!

ErikF

Posted 2018-11-02T18:29:09.540

Reputation: 2 149

147 – ceilingcat – 2020-02-27T05:04:34.020

1

Stax, 16 bytes

∞╠mQ╛3mQ->n▀÷↕┐ò

Run and debug it

recursive

Posted 2018-11-02T18:29:09.540

Reputation: 8 616

1

Japt, 18 bytes

fè`^[Vv]*m!$` ®èo

Try it online!

Saved a byte by taking input as an array of lines.

Includes an unprintable character between ] and *.

Explanation:

fè                   Get the line(s) that match
  `^[Vv]*m!$`          The provided RegEx with a little compression
              ®èo    Count the number of "o" in that line if it exists

Kamil Drakari

Posted 2018-11-02T18:29:09.540

Reputation: 3 461

119 bytes – Shaggy – 2018-11-02T22:37:17.300

Also 19 bytes – Shaggy – 2018-11-02T23:13:53.577

Actually, as input can be an array of lines, you can knock the first byte off my first comment above. – Shaggy – 2018-11-03T12:07:15.053

@Shaggy I can't find anywhere in the question that specifies that input can be an array of lines, and it doesn't seem to be listed in the default I/O methods that a multiline string can be taken as an array of lines. It seems likely to be reasonable, but I'll wait for confirmation first. – Kamil Drakari – 2018-11-03T17:34:50.147

1

Haskell, 75 71 69 bytes

f s=[length n-2|r<-lines s,n<-scanr(:)"m!"$'o'<$r,v<-"Vv",r==v:'r':n]

Try it online!

No regex. Instead builds all valid Vrooom!-strings up to a sufficient length and compares the lines of the input against them, collecting the number of os in a list. Thus for invalid inputs an empty list is returned.

Laikoni

Posted 2018-11-02T18:29:09.540

Reputation: 23 676

1

C (gcc), 138 124 bytes

Here's the boring regex way.

#include<regex.h>
f(char*s){regmatch_t m[9];regcomp(m+2,"^[Vv]r(o*)m!$",5);s=regexec(m+2,s,2,m,0)?-1:m[1].rm_eo-m[1].rm_so;}

Try it online!

ErikF

Posted 2018-11-02T18:29:09.540

Reputation: 2 149

1

C (gcc), 104 100 bytes

s;main(c,n){for(;gets(&s);sscanf(&s,"v%*[o]%nm%c%c",&n,&c,&c)-1||c-33?:printf("%d",n-2))s=s-768|32;}

Try it online!

Output the n for each valid line, exactly in the requirement(nothing if no valid line, the n if exactly one)

int s; // Use as a char[]
main(c){
  while(gets(&s)) {
    s=s-768|32; // byte 0: 'V'=>'v'; byte 1: 'r'=>'o', 'o'=>'l'
    if (sscanf(&s,"v%[o]m%c%c",&s,&c,&c)==2 && c=='!') {
    // The last '%c' get nothing if it's EndOfLine
      printf("%d",strlen(&s)-1))
    }
  }
}

l4m2

Posted 2018-11-02T18:29:09.540

Reputation: 5 985

It's so funny that the regex answer is longer than this – Windmill Cookies – 2018-11-03T11:12:13.450

@WindmillCookies GCC need extra code to support regex – l4m2 – 2018-11-03T11:29:31.853

hmm. seems like names related to regexes are extremely long – Windmill Cookies – 2018-11-03T11:32:59.707

0

Pyth, 28 bytes

IJjb.nm:rd0"^vro*m!$"1.z/J\o

Try it online!

Cowabunghole

Posted 2018-11-02T18:29:09.540

Reputation: 1 590

0

Pyth, 20 bytes

/R\o:#"^Vro*m!$"1cQb

Outputs as a list containing only the number of 'o's, or an empty list if there's no Vroom.
Try it here

Explanation

/R\o:#"^Vro*m!$"1cQb
                 cQb  Split on newlines.
    :#"^Vro*m!$"1     Filter the ones that match the regex.
/R\o                  Count the `o`s in each remaining element.

user48543

Posted 2018-11-02T18:29:09.540

Reputation:

0

C# (.NET Core), 134 122 bytes

for(var a="";a!=null;a=Console.ReadLine())if(new Regex(@"^[Vv]ro*m!$").Match(a).Success)Console.Write(a.Count(x=>x=='o'));

Try it online!

-12 bytes: moved null check into for loop and removed brackets

Ungolfed:

for(var a = ""; a != null; a = Console.ReadLine())  // initialize a, and while a isn't null, set to new line from console
    if(new Regex(@"^[Vv]ro*m!$")                        // set regex
                        .Match(a).Success)              // check if the line from the console matches
        Console.Write(a.Count(x => x == 'o'));              // write the number of 'o's to the console

Meerkat

Posted 2018-11-02T18:29:09.540

Reputation: 371

-10 bytes with C# 6's null-coalescing and conditional operators, also unnecessary {} when using just one statement in the for loop: for(var a="";;a=Console.ReadLine())Console.WriteLine(new Regex(@"^[Vv]ro*m!$").Match(a??"").Success?a.Count(x =>x=='o'):-1); – Ivan García Topete – 2018-11-02T21:37:19.120

Also, this needs using System.Linq; using System.Text.RegularExpressions;, not sure if this is important lol – Ivan García Topete – 2018-11-02T21:46:25.183

The code you provided doesn't actually work, as it will not only output a -1 for every line that it doesn't work on, but it will output -1s forever as there is no check for null. – Meerkat – 2018-11-05T14:24:23.680

No, it won't. a = Console.ReadLine() makes the loop, so each time you're requesting input for the loop to go on, if there is no input, the loop is just waiting, not printing -1 forever – Ivan García Topete – 2018-11-05T15:28:31.077

Proof of concept. Even if it did work as you said, a never-ending loop is not ideal behavior.

Regardless, I've moved the null check into the for loop, which removes the brackets (and makes the code shorter than your suggestion).

– Meerkat – 2018-11-05T16:01:16.700

0

Pip, 21 bytes

a~,`^[Vv]r(o*)m!$`#$1

Try it online!

Match regex ^[Vv]r(o*)m!$ in multiline mode; output length of capture group.

DLosc

Posted 2018-11-02T18:29:09.540

Reputation: 21 213

0

C++, MSVC, 164 159 bytes

-5 bytes thanks to Zacharý

It compiles even with the regex header only

#include<regex>
using namespace std;int f(vector<string>i){smatch m;for(auto&e:i)if(regex_match(e,m,regex("^[Vv]ro*m!$")))return m[0].str().size()-4;return-1;}

Tests :

std::cout << "Vrom!" << " -> " << f({ "Vrom!" }) << '\n';
std::cout << "vrooooooom!" << " -> " << f({ "vrooooooom!" }) << '\n';
std::cout << "Hello, Vroom!" << " -> " << f({ "Hello, Vroom!" }) << '\n';
std::cout << "Foo bar boo baz \\n Vrooom! \\n hi" << " -> " << f({ "Foo bar boo baz", "Vrooom!", "hi" }) << '\n';
std::cout << "Vrm!ooo" << " -> " << f({ "Vrm!ooo" }) << '\n';
std::cout << "PPCG puzzlers pie" << " -> " << f({ "PPCG puzzlers pie" }) << '\n';
std::cout << "hallo \\n vROOOm!" << " -> " << f({ "hallo", "vROOOm!" }) << '\n';

HatsuPointerKun

Posted 2018-11-02T18:29:09.540

Reputation: 1 891

1I think using namespace std; would save a few bytes – Zacharý – 2018-11-05T14:30:07.620

0

sfk, 94 bytes

xex -i -case "_[lstart][char of Vv]r[chars of o]m![lend]_[part 4]o_" +linelen +calc "#text-1" 

Try it online!

Gives -1 when you're not vrooming.

Οurous

Posted 2018-11-02T18:29:09.540

Reputation: 7 916

0

JavaScript, 90 73 61 bytes

_=>_.replace(/^[Vv]r(o*)m!$|[^\1]/mg,(m,a)=>a||'').length||-1

Try it online!

Replace characters that are not captured at (o*) with empty string, return length of string containing only "o" or -1 if resulting string is empty.

guest271314

Posted 2018-11-02T18:29:09.540

Reputation: 1

0

Ruby, 28 29 bytes

p$_[/^[vV]r(o*)m!$/].count ?o

Try it online!

Multi-line strings require three more bytes. I'm not sure if that's a hard requirement. If so, I'll update this.

->l{l[/^[Vv]r(o*)m!$/].count ?o}

canhascodez

Posted 2018-11-02T18:29:09.540

Reputation: 201

How can you test multi-line strings? – Laikoni – 2018-11-03T09:17:10.327

1Fail on VROM! – l4m2 – 2018-11-03T10:59:59.653

0

Red, 104 bytes

func[s][n:""if parse/case s[opt[thru"^/"]["V"|"v"]"r"copy n any"o""m!"opt["^/"to end]][print length? n]]

Try it online!

A straightforward solution. Red's parse is cool and readable, but too long compared to regex

Red []
f: func [ s ] [
    n: ""
    if parse/case s [
             opt [ thru newline ]
             [ "V" | "v" ]
             "r"
             copy n any "o"
             "m!"
             opt [ newline to end ]
    ] [ print length? n ]
]

Galen Ivanov

Posted 2018-11-02T18:29:09.540

Reputation: 13 815

0

J, 35 bytes

(]{~0<{.)(1{'^[Vv]r(o*)m!'rxmatch])

Returns negative 1 if the pattern doesn't match.

hoosierEE

Posted 2018-11-02T18:29:09.540

Reputation: 760

0

Ruby, 32 bytes

->n{n=~/^[Vv]r(o*)m!$/m;$1.size}

Matches the string to the regex, then uses Ruby's magic regex group variables to get the first group's size.

Call it like so:

x=->n{n=~/^[Vv]r(o*)m!$/m;$1.size}
x["Vrooooooooooooooooooooom!"] # returns 21

NO_BOOT_DEVICE

Posted 2018-11-02T18:29:09.540

Reputation: 419

0

Clojure, 90 bytes

#(do(def a(clojure.string/replace % #"(?ms).*^[Vv]r(o*)m!$.*""$1"))(if(= a %)-1(count a)))

Try it online!

This anonymous function returns the number of "o"s in the vroom string, or -1 if there is no valid vroom string.

Readable version

(fn [s]
  (def a (clojure.string/replace s #"(?ms).*^[Vv]r(o*)m!$.*" "$1"))
  (if (= a s) -1 (count a)))

Explanation

#"(?ms).*^[Vv]r(o*)m!$.*" ; This regex matches any string that contains a valid vroom string. The first capturing group contains only the "o"s in the vroom string
(clojure.string/replace s #"(?ms).*^[Vv]r(o*)m!$.*" "$1") ; Replaces a match of the above regex with its first capturing group. The resulting string is stored in the variable a
(if (= a s) -1 (count a))) ; a equals s if and only if there is no valid vroom string, so if a equal s we return -1. If there is a valid vroom string, a contains only the "o"s from the vroom string, so we return the length of a

TheGreatGeek

Posted 2018-11-02T18:29:09.540

Reputation: 111

0

perl -nE, 35 bytes

$s=length$1if/^[Vv]r(o*)m!$/}{say$s

This uses the Eskimo greeting (}{) which abuses the a quick on how the -n option is dealt with by perl.

user73921

Posted 2018-11-02T18:29:09.540

Reputation:

0

Java 8, 109 bytes

s->{int r=-1;for(var l:s.split("\n"))r=l.matches("[Vv]ro*m\\!")?l.replaceAll("[^o]","").length():r;return r;}

Try it online.

Explanation:

s->{                             // Method with String parameter and integer return-type
  int r=-1;                      //  Result-integer, starting at -1
  for(var l:s.split("\n"))       //  Loop over the lines:
    r=l.matches("[Vv]ro*m\\!")?  //   If the current line matches the regex:
       l.replaceAll("[^o]","").length()
                                 //    Change `r` to the amount of "o"'s in it
      :                          //   Else:
       r;                        //    Leave the result `r` unchanged
  return r;}                     //  Return the result

Kevin Cruijssen

Posted 2018-11-02T18:29:09.540

Reputation: 67 575

0

05AB1E, 39 37 bytes

|ʒć„VvsåsÁÁD…m!rÅ?s¦¦¦Ù'oså)P}Dgi`'o¢

Although 05AB1E is a golfing languages, regex-based challenges are definitely not its strong suite, since it has no regex-builtins.

Outputs [] if no match was found.

Try it online or verify all test cases.

Explanation:

|              # Get the input split by newlines
 ʒ             # Filter it by:
  ć            #  Head extracted: Pop and push the remainder and head-character
               #   i.e. "vrm!" → "rm!" and "v"
               #   i.e. "Vroaom!" → "roaom!" and "V"
   „Vvså       #  Is this head character in the string "Vv"?
               #   i.e. "v" → 1 (truthy)
               #   i.e. "V" → 1 (truthy)
  s            #  Swap so the remainder is at the top of the stack again
   ÁÁ          #  Rotate it twice to the right
               #   i.e. "rm!" → "m!r"
               #   i.e. "roaom!" → "m!roao"
     D         #  Duplicate it
      …m!rÅ?   #  Does the rotated remainder start with "m!r"?
               #   i.e. "m!r" → 1 (truthy)
               #   i.e. "m!roao" → 1 (truthy)
  s¦¦¦         #  Remove the first three characters from the duplicated rotated remainder
               #   i.e. "m!r" → ""
               #   i.e. "m!roao" → "oao"
      Ù        #  Uniquify, leaving only distinct characters
               #   i.e. "" → ""
               #   i.e. "oao" → "oa"
       'oså   '#  Is this uniquified string in the string "o"?
               #   i.e. "" → 1 (truthy)
               #   i.e. "oa" → 0 (falsey)
  )P           #  Check if all three checks above are truthy
               #   i.e. [1,1,1] → 1 (truthy)
               #   i.e. [1,1,0] → 0 (falsey)
 }             # Close the filter
  D            # After the filter, duplicate the list
   gi          # If its length is 1:
               #   i.e. ["vrm!"] → 1 (truthy)
               #   i.e. [] → 0 (falsey)
     `         #  Push the value in this list to the stack
               #   i.e. ["vrm!"] → "vrm!"
      'o¢     '#  And count the amount of "o" in it (and output implicitly)
               #   i.e. "vrm!" → 0
               # (Implicit else:)
               #  (Implicitly output the duplicated empty list)
               #   i.e. []

Kevin Cruijssen

Posted 2018-11-02T18:29:09.540

Reputation: 67 575

0

16-bit x86 assembly code, 35 bytes


l1: lodsb          ;fetch a byte
    cbw            ;zero AH to allow returning 0
    cwd            ;zero counter
l2: and   al, 0dfh ;lower- to upper-case
    je    l4       ;exit if end of string
    cmp   al, 'V'
    jne   l1
    lodsb          ;fetch a byte
    cmp   al, 'r'
    jne   l2       ;if not 'r', branch to try 'v' or 'V' instead
l3: lodsb          ;fetch a byte
    test  al, al
    je    l4       ;exit if end of string
    inc   dx       ;speculatively count 'o's
    cmp   al, 'o'
    je    l3       ;loop while 'o'
    lodsw          ;fetch two bytes
    dec   si       ;align pointer as though only one byte fetched
                   ;in case of mismatch at the end
    cmp   ax, '!m' ;Intel backwards ordering
    jne   l2       ;loop while not matching complete string
    xchg  dx, ax   ;return count only if match
l4: ret

Accepts a pointer to the string in si, returns the count (or 0) in ax.

peter ferrie

Posted 2018-11-02T18:29:09.540

Reputation: 804

Can't tell vrm! from foo? – l4m2 – 2018-11-06T09:59:36.893

0

Kotlin, 55 bytes

{Regex("^[Vv]ro*m!\$").find(it)?.value?.count{it=='o'}}

Try it online!

snail_

Posted 2018-11-02T18:29:09.540

Reputation: 1 982