Search on the blog

2020年2月7日金曜日

c++17 で stg::lcm が追加されててハマった話

 Codeforcesのk-roundingという問題を解いたらWAが出た。

「nとkが与えられるので、末尾に0がk個以上ついてnで割れる最小の自然数を求めよ」という問題で、nと10^k の最小公倍数を求めれば良さそうなので、以下のようなコードをsubmit。

#include <bits/stdc++.h>
 
using namespace std;
 
#define REP(i,n) for(int i=0; i<(int)(n); i++)
#define FOR(i,b,e) for (int i=(int)(b); i<(int)(e); i++)
#define ALL(x) (x).begin(), (x).end()
 
const double PI = acos(-1);
 
long long gcd(long long a, long long b) {
  if (b == 0)
    return a;
  return gcd(b, a%b);    
}
 
long long lcm(long long a, long long b) {
  return a / gcd(a, b) * b;
}
 
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
 
  int n, k;
  cin >> n >> k;
 
  int x = 1;
  REP (i, k) x *= 10;
 
  cout << lcm(n, x) << endl;
  
  return 0;
}

結果Wong Answer。
詳細なテストケースを見てみると、n = 123456789, k = 8 で 1566078208 と出力されている。試しにローカルで動かしてみると12345678900000000と正答を出力している。

上のコードでは main の中では int を使っているけど引数としてlcmに渡した時点でlong longになるのでオーバーフローはしないはずだが、試しにmainを以下のように変えてsubmitしてみると予想に反してAC。

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
 
  long long n, k;
  cin >> n >> k;
 
  long long x = 1;
  REP (i, k) x *= 10;
 
  cout << lcm(n, x) << endl;
  
  return 0;
}

サーバでは g++17 で実行されるけどローカルだとg++17じゃないなと気づいて、もしやと思って調べると std に gcdlcm が追加されてました。引数を int で渡すとこちらが実行されていたようです。

とりあえずローカルでコンパイルするときに g++17 を使うようにしたものの、サンプルケースにオーバーフローするものがないと意図せず std::lcm の方が呼び出しされていることに気づけないので、自分のライブラリ関数の名前を変えた方がいい気がしています。


2019年10月3日木曜日

ラッパー、バインディング、ポーティング

同じような文脈で使っていたが、それぞれ意味が異なるらしい。

意味の違い
ラッパー ライブラリの機能を同じ言語でラッピングしたもの。
バインディング ライブラリの機能を別の言語でラッピングしたもの。
ポーティング ライブラリを別の言語で書き換えたもの。

使い方
  • Pythonで書かれた XXXライブラリは便利だが冗長なコードを毎回書かないといけないので、シンプルなインターフェースを持つラッパーを書いた。
  • YYYライブラリは便利だけどC言語向けにしか提供されていないので、Javaバインディングを書いた。
  • ZZZライブラリはPythonで書かれていてパフォーマンス的に問題があるので、Cのポーティングを書いた。
参考

2019年8月15日木曜日

GITADORA DM スキル 2727.21

 7月は海外にいたので久しくギタドラできていなかった。お盆休みになったので空き時間を利用して叩きにいってきた。

最近の練習曲たち。

GITADORA始めてから初めてぶつかった壁が U.N. オーエンのBasicだった。半年経ってAdvancedを叩けるようになった。意外と簡単にSを取れた。スネアだけを淡々と叩くところが難しくてリズムを見失ってしまうが、ギターのリフを意識すると拍の頭が分かりやすくなってリズムを取りやすそう。

タムが難しい。最初三連符と勘違いしていたが、16分、16分、8分である。これまで画面に流れてくる音符にタイミングを合わせて叩くだけだったが、小節の中で音がどう分割されているかを意識しないといけないと気づいた。タム回し以外のパートは簡単。


昔苦手だったエイトビートの叩き方(Hを裏拍でのみ叩く)だが、苦手意識がなくなっていた。途中でRが入ってくるところのパターンが分からなくて叩けなかったが、よく見るとHをRにしただけのパターンなので、それがわかると普通に叩けた。

2019年6月29日土曜日

Con Calma

 Snow の Informer (1992年) が Daddy Yankee + Katy Perry feat. Snow で新しくリリースされた。

 スペイン語のラップは何て言ってるか分からないけど、かっこいい。Katy Perry も少しスペイン語の歌詞を歌っている。

¿Cómo te llamas baby?
Hola me llamo Katy!


 久々にスペイン語の勉強してみたくなったのでサビの部分を訳してみた。

Con calma, yo quiero ver como ella lo menea
Calmly, I want to see how she wags it

Mueve ese poom-poom, girl
Move that poom-poom, girl

Es un asesina, cuando baila quiere que to' el mundo la vea
She is a murderer, when she dances, she wants the world to see her.

I like your poom-poom, girl
I like your poom-poom, girl

Con calma, yo quiero ver como ella lo menea
Calmly, I want to see how she wags it

Mueve ese poom-poom, girl
Move that poom-poom, girl

Tiene adrenalina, en medio 'e la pista, vente hazme lo que sea
She has adrenaline, in the middle of the track, come do me whatever you want

I like your poom-poom, girl
I like your poom-poom, girl

なかなか刺激的な歌詞だ。ラテン系の女性は情熱的だ。

プロジェクトごとの環境変数の管理

まえがき

 複数のプロジェクト開発を担当していると、プロジェクトごとにさまざまな設定を管理しないといけない。

 たとえばプロジェクトごとに aws アカウントが異なる場合は、 profile を作っておいて aws コマンドを実行するときに profile オプションを付ける必要がある。しかし、プロジェクト数が多くなってくると、profile 名何だっけ?となることがある。

 他にもdbの接続情報などをプロジェクトごとに使い分けたかったりする。

direnv

 direnv というツールを使うとディレクトリごとに環境変数を管理できるらしい。.envrc というファイルを作って環境変数を定義すると、そのディレクトリの中でのみ有効になる。

 例として、projectX と projectY というディレクリを作って設定をしてみる。

$ mkdir projectX
$ cd projectX
$ echo "export MY_PWD=hogehoge" >.envrc
$ direnv allow

$ mkdir projectY
$ cd projectY
$ echo "export MY_PWD=fugafuga" >.envrc
$ direnv allow

 ディレクトリごとに環境変数が切り替わっていることを確認してみる。

$ cd projectX
$ echo $MY_PWD
hogehoge

$ cd projectY
$ echo $MY_PWD
fugafuga

これは便利!

2019年6月22日土曜日

Scala: implicit の使い方

Scala の implicit の使い所をまとめておく。

Pimp My Library

標準機能やサードパーティライブラリのクラスを拡張したいときに使う。

object ImplicitInt {
  implicit class RichInt(val x: Int) {
    def negate: Int = -x
    def square: Int = x * x
  }
}

上記のような implicit class を作っておいてimport すると、Int型の変数で squareメソッド、negate メソッドが使えるようになる。

import ImplicitInt._

object Main {
  def main(args: Array[String]): Unit = {
    // pimp my library
    val x = 100
    println(x.square)  // 10000
    println(x.negate)  // -100
  }
}

Implicit Conversion

暗黙の型変換。

case class Rational(real: Double, imag: Double) {
  def +(that: Rational) = Rational(real + that.real, imag + that.imag)
}

object Rational {
  implicit def double2Rational(x: Double): Rational = new Rational(x, 0)
}

上記のように複素数を扱うクラスを定義したとする。複素数と実数の足し算をしたい場合、implicit conversion を使うと以下のように書ける。わざわざ Double から Rational クラスを明示的につくらなくていいので便利。


object Main {
  def main(args: Array[String]): Unit = {
    val x = Rational(1.0, 1.0)
    val y = x + 2.0
    println(y)  // Rational(3.0,1.0)
  }
}

Implicit Parameter

暗黙的なパラメータ。実行コンテキストなどのパラメータを暗黙的にメソッドに渡してくれる。

import scala.concurrent.{ExecutionContext, Future}

class RemoteCall {
  def get(x: Int)(implicit ex: ExecutionContext): Future[Int] = Future {
    println("heavy remote call...")
    Thread.sleep(5000)
    x
  }
}

上記のような重い処理があって、メインスレッドとは別のスレッドで実行したいとする。 ExecutionContext を implicit で受け取れるように定義されているため、以下のように実行コンテキストを渡すことができる。

import java.util.concurrent.Executors

import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService}
import scala.util.{Failure, Success}

object Main {
  def main(args: Array[String]): Unit = {
    implicit val ex: ExecutionContextExecutorService =
      ExecutionContext.fromExecutorService(Executors.newSingleThreadExecutor())

    val remoteCall = new RemoteCall
    remoteCall.get(123) onComplete {
      case Success(r) =>
        println(r)
        ex.shutdown()
      case Failure(t) => println(t.getMessage)
    }
    println("do something else")
  }
}

他にもデータベース接続をするときに、接続まわりを担当するクラスを implicit parameter で渡すなどの使い方がある。

2019年6月15日土曜日

GITADORA DM スキル 2286.19

 ネームカラーが黄色になった。スティックを買ってメトロノームにあわせて叩く練習を始めた。


最近の練習曲は以下のとおり。

  • 高校生のときに流行っていた懐メロ
  • 難易度のわりに簡単
  • 気持ち早めに叩きにいくと Perfect が出やすかった 

  • ドンタン、ドンタ、ドンドタン、ドンタンみたいなパターンが独特
  • サビ前のスネアの連打が決まると気持ちいい

  • 難易度のわりに難しい気がする
  • 最初挑戦したときはまともに叩けるようになる気がまったくしなかった
  • 16分音符のタム回しがキマると気持ちいい