9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

AtCoder に登録したら解くべき精選過去問 10 問を V言語 で解いてみた

Last updated at Posted at 2019-06-25

2023/3/30追記:
本記事には古い内容が含まれています。現在のV言語を用いた新しい記事を投稿したので、最新の内容をお求めの方は以下のリンクからどうぞ。


最近何かと話題のV言語が6月22日にオープンソースで公開されたので、生まれたてのV言語君にはABSをやってもらいます。

V言語ホームページ https://vlang.io/
V言語GitHub https://github.com/vlang/v
ABS(AtCoder) https://atcoder.jp/contests/abs

AtCoderにV言語はないが?????????

V言語はC言語と密接に関わっていて、Cで使えるライブラリはほぼ使えたり、Cのソースコードを吐いたりしてくれます。この吐き出されたソースコードを貼っつけて実行します。50000byte365000byte(2021/7/1現在)とかになりますが、気にしたら負けです。

また、V言語は出力は優秀なんですが、標準入力は文字列しか取れません(2021/7/1現在)。ライブラリが整ったらそれを使ったソースコードに更新します。が、今は仕方がないのでCからscanfを引っ張ってきます。面倒くさい、-^^-まるでどこかのJavaScr

2019/11/9追記:V言語がAtCoderの言語アプデで入りそうなんですが、安定でない0.1.xで大丈夫なのか…?私的には0.2.xを待った方がいいと思われるが。

2021/7/1追記:0.2.x来てますが、文法もまだ揺れてるし0.3.x待ちですかね。まぁ大丈夫だとは思いますが。ライブラリも欲しいところ。

2023/3/27追記:Language UpdateでV言語が候補に上がっていてLanguage Test 202301でV言語を使うことができます。なお、この記事のコードは古いため現在のV言語ではコンパイルできない可能性があります。現在AtCoderで使えるV言語での解答例はこちらで確認できます。

入力

C言語のライブラリの関数はC.hogeで書けます。stdio.hはもう入ってるのでincludeする必要はありません。
また、Cの文字列はbyteの配列ですが、V言語のstringとして扱うには文字列の長さを含んでラップする必要があります。
2021/7/1現在はもっといい方法としてV言語のbyteの配列の0番目のポインタをCに渡し、bytestrメソッドでstringに変換できます。

fn C.scanf(&char, ...voidptr) int

fn scan_int() int {
    scanned := 0
    C.scanf(c'%d', &scanned)
    return scanned
}

fn scan_string(max int) string {
    arr := []u8{len: max}
    unsafe { C.scanf(c'%s', &arr[0]) }
    return unsafe { tos_clone(&arr[0]) }
}

解答

0問目 PracticeA - はじめてのあっとこーだー(Welcome to AtCoder)

fn main() {
    num := scan_int() + scan_int() + scan_int()
    hoge := scan_string(100)
    println('$num $hoge')
}

入出力を問われている問題です。

変数の宣言には:=を、代入には=を用います。
V言語は文字列連結をしたり、文字列にリテラルを埋め込んだりできるので出力に関してはとても優秀です。

1問目 ABC086A - Product

fn main() {
    a := scan_int()
    b := scan_int()
    println(if a*b%2 == 0 {'Even'} else {'Odd'}) 
}

簡単な数値演算です。

V言語のif文はRustやKotlinみたいな最近の言語らしく、三項演算子のように値を返すことができます。

2問目 ABC081A - Placing Marbles

fn main() {
    mut ans := 0
    m := scan_string(3)
    one := `1`
    for i in m {
        if i == one {ans++}
    }
    println(ans)
}

簡単な文字列処理です。

1のバイトコードの取得にはバッククォートを用います。
配列や文字列はfor...in構文が使えます。

3問目 ABC081B - Shift only

fn main() {
    mut max := 1000000
    n := scan_int()
    for _ in 0..n {
        mut hoge := scan_int()
        mut num := 0
        for {
            if hoge%2 == 0 {
                num++
                hoge /= 2
            } else {
                break
            }
        }
        if num < max {
            max = num
        }
    }
    println(max)
}

2で割れる回数を求めてその最小値を出します。

**「いくらfor...inが使いたいからってnum := iなんてする必要ないじゃない!」**ごめんなさい、書きたかった12
使わない数値は、特殊な変数_に放り込めばいいようになったようです。n回繰り返しにはこれを使えばよさげ
2019/11/9追記:for i in start..endという構文が書けるようになったようです。[0].repeat(n)とはおさらば

4問目 ABC087B - Coins

fn main() {
    a := scan_int()
    b := scan_int()
    c := scan_int()
    x := scan_int()
    mut ans := 0
    mut i := 0
    mut j := 0
    for i <= x/500 {
        j = 0
        for j <= (x-i*500)/100 {
            k := x - i*500 - j*100
            if a >= i && b >= j && c >= k/50 {
                ans++
            }
            j++
        }
        i++
    }
    println(ans)
}

500円玉と100円玉の枚数で全探索をします。

for文はCのwhile文のように使うことができます(これが普通)。

5問目 ABC083B - Some Sums

fn main() {
    n := scan_int()
    a := scan_int()
    b := scan_int()
    mut ans := 0
    for i := 1; i <= n; i++ {
        istr := i.str()
        mut sum := 0
        for c in istr {
            sum += int(c-`0`)
        }
        if a <= sum && sum <= b {
            ans += i
        }
    }
    println(ans)
}

1からnの数について、全ての桁を足します。
今回は数値を文字列に変換し、文字が表す数値を全て足しました。

Cのfor文みたいにもfor文を使うことができます。for文えらい万能やな

6問目 ABC088B - Card Game for Two

fn main() {
    n := scan_int()
    mut arr := []int{len: n, init: 0}
    for i in 0..n {
        arr[i] = scan_int()
    }
    arr.sort(a > b)
    mut ans := 0
    mut t := 1
    for i in arr {
        ans += t*i
        t = -t
    }
    println(ans)
}

降順にクイックソートして足し引きをします。

クイックソートはarray構造体に組み込まれているsort関数を利用します。
sortは特殊な関数です。abという特殊な変数が渡され、括弧内に式を書けばそれがソートの条件文として機能します。

7問目 ABC085B - Kagami Mochi

fn main() {
    n := scan_int()
    mut arr := [0].repeat(n)
    for i in 0..n {
        arr[i] = scan_int()
    }
    arr.sort()
    mut ans := 1
    mut t := arr[0]
    for i in arr {
        if i != t {
            t = i
            ans++
        }
    }
    println(ans)
}

昇順にクイックソートして被りを抜いて数えます。

sort関数の条件文を省略すると勝手に昇順になります。

8問目 ABC085C - Otoshidama

fn main() {
    n := scan_int()
    y := scan_int()
    for i := 0; i <= n; i++ {
        for j := 0; j <= n-i; j++ {
            k := n-i-j
            if i*1000 + j*5000 + k*10000 == y {
                println('$k $j $i')
                return
            }
        }
    }
    println('-1 -1 -1')
}

お札の枚数で全探索します。

テンプレ文字列は文明の利器。

9問目 ABC049C - 白昼夢 / Daydream

fn main() {
    mut str := scan_string(100000)
    if str.replace('eraser','').replace('erase','').replace('dreamer','').replace('dream','').len == 0 {
        println('YES')
    } else {
        println('NO')
    }
}

・・・
 
 
 
・・・・・・**嘘解法です!!**でもreplaceを連ねて書けるの、きもちいい。

10問目 ABC086C - Traveling

fn main() {
    n := scan_int()
    mut t := 0
    mut x := 0
    mut y := 0
    for i in 0..n {
        t0 := scan_int()
        x0 := scan_int()
        y0 := scan_int()
        dt := t0-t
        dx := x0-x
        dy := y0-y
        if dx+dy > dt || (dt-dx-dy)%2 == 1 {
            println('No')
            return
        }
        t = t0
        x = x0
        y = y0
    }
    println('Yes')
}

歩数が足りるかどうかと、往復で時間をつぶしてたどり着けるか(偶奇でわかる)を判定します。

完走した感想

まだEarly Access版なので足りない部分は存在したものの、これからたぶん伸びていく言語なのでそこはたぶん期待できます。簡単な構文で書けて速度も速い、これは今後次第で競プロにピッタリな言語になりえるのではないでしょうか。

更新履歴

2019/7/4 いつの間にか文字のバイト値を取得する構文ができてたのでバッククォートに変更
2019/9/25 stringとかrepeatとかアンダーバーとか他にも色々更新が入ってたので更新
2019/11/9 for i in start..endを追加。endiに含まれないのでいつものfor文の感覚で使える。
2021/7/1 0.2.xも出てるし重い腰を上げて更新するかとなったので。配列やunsafeなとこ周りが結構変わってます。

  1. V言語ではある値である長さの配列を[]型名{len: 長さ, init: 初期値(省略可)}で作成できます。

  2. V言語では宣言した変数を使用しなければ警告が出ます。以前は必ず使用しなければエラーになっていました。

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?