20190415のJavaに関する記事は5件です。

JAVA_HOMEとPath

JAVA_HOMEとPath

windowsでJavaのインストールをしないといけない時にネックになってくるのが環境変数

環境変数とは

Javaとかにはバージョンごとにフォルダにその情報とかが入っている。
そこまでの階層/Library/Java/JavaVirtualachine/jdk{バージョン}/をさすのはめんどくさいから、JAVA_HOMEとかPathという環境変数に入れて楽に扱おうというもの。

よく「Pathが通らない〜」というのは環境変数の中身が間違っていて目的の階層にいけない事

JAVA_HOMEとPathの違い

どちらも環境変数である。
ただ、アプリケーションによってJAVA_HOMEでJavaの情報を取得したりPathでJavaの情報を取得したりするので両方設定しておくといい。

以下設定情報。
なおJDK(Java)はC:¥Program Files¥Java¥jdk1.8.0_101にインストールされてるとします。
詳しい設定方法はこちら

JAVA_HOME

JAVA_HOME = C:¥Program Files¥Java¥jdk1.8.0_101

JDKがインストールされているディレクトリを指定する

Path

Path = C:¥Program Files¥Java¥jdk1.8.0_101¥bin

Javaのソースコードをコンパイルしたり実行したりするファイルが¥bin以下に入っているのでそこを指定。

参考にさせていただいた記事

ありがとうございました。
ちゃんとできてる?Javaの環境変数の設定方法
PATHの設定及び環境変数JAVA_HOMEの設定
JAVA_HOMEについて

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

java kotlin IntとIntの除算(割り算)にご注意

なんでこんな簡単なことにハマったのでしょう?
私と同じようにハマって時間を無駄にする方がいないように備忘録

下記は当然の如く0.25と出ると思っていましたが...

        var rate: Double = 0.0
        rate = 1 / 4
        Log.v("TEST:", "rate:${rate}")

下記のようなコンパイルエラーがでる。

Type mismatch: inferred type is Int but Double was expected

google翻訳様:「型が一致しません:推定型はIntですがDoubleが必要です」

そんなことわかっておるワイ!!!

ん? あっ Σ(゚д゚;) ,,,, そういう事か。
IntとIntの計算なので計算結果の型の判定がIntになっていたんですね...
俺よ、なぜ気づかなかった。。。

ということで解決策。どっちか、もしくは両方をDoubleに合わせてやればよい。

        val num1 = 1.toDouble()
        val num2 = 4.toDouble()

        val aaa = num1 / num2

        Log.v("TEST:", "rate = ${aaa}")
V/TEST:: rate = 0.25

はい。想定どおりの結果が返ってきました。
自分の頭の悪さに涙が止まらんです。

補足

ちなみに...

        val aaa = (1/4).toDouble()
        Log.v("TEST:", "rate = ${aaa}")
V/TEST:: rate = 0.0

こうすると 計算結果がIntで来てそれをDoubleに変換しているみたいになるから
想定する結果が返ってきません。
10 / 4 とかだと 2.0 になるから注意。

では、よい kotlin 生活を!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

AtCoder に登録したら解くべき精選過去問 10 問を Java,StreamAPIで解いてみた

はじめに

AtCoder に登録したら次にやること ~ これだけ解けば十分闘える!過去問精選 10 問 ~ で紹介されていた10問をJava8, StreamAPIを使って解いた。
AtCoder Beginners Selectionはこちら
StreamAPIの勉強のためにやったのでマサカリを糧にしたい。

前提

  • パフォーマンスはとりあえず無視するが、入力はBufferedReaderで受け取る
  • できるだけ手続き的な書き方を避ける

ABC086A Product

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;

class Main {
    public static void main(String[] args) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = br.readLine();
        System.out.println(
                Arrays.stream(input.split(" "))
                        .mapToInt(Integer::parseInt)
                        .reduce(1,(x, y) -> x * y % 2) != 0 ? "Odd":"Even"
        );
    }
}

ABC081A Placing Marbles

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;

class Main {
    public static void main(String[] args) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = br.readLine();
        System.out.println(
                Arrays.stream(input.split(""))
                        .filter(i -> i.equals("1"))
                        .count()
        );
    }
}

ABC081B Shift only

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;

class Main {
    public static void main(String[] args) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = br.readLine();
        int[] intArray = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
        for(int count = 0; ; count++) {
            if(Arrays.stream(intArray).allMatch(i -> i % 2 == 0)) {
                intArray = Arrays.stream(intArray).map(i -> i / 2).toArray();
            } else {
                System.out.println(count);
                break;
            }
        }
    }
}

BufferedReaderを使う都合で、行で受け取って配列に分割してStreamに変換するのがやりやすかったからinputを受け取っても使わない

ABC087B Coins

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.IntStream;

class Main {
    public static void main(String[] args) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int A = Integer.parseInt(br.readLine());
        int B = Integer.parseInt(br.readLine());
        int C = Integer.parseInt(br.readLine());
        int X = Integer.parseInt(br.readLine());

        final long count = IntStream.rangeClosed(0, A).map(i -> i * 500)
                        .flatMap(i -> IntStream.rangeClosed(0, B).map(j -> i + 100 * j))
                        .flatMap(i -> IntStream.rangeClosed(0, C).map(j -> i + 50 * j))
                        .filter(i -> i == X)
                        .count();

        System.out.println(count);
    }
}

ABC083B Some Sums

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.IntStream;
import java.util.stream.Stream;

class Main {

    public static void main(String args[]) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int[] nab = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();

        final long count = IntStream.rangeClosed(1, nab[0]).filter(num -> {
            int sum = Arrays.stream(String.valueOf(num).split("")).mapToInt(Integer::parseInt).sum();
            return sum >= nab[1] && sum <= nab[2];
        })
        .sum();

        System.out.println(count);
    }
}

ABC088B Card Game for Two

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

class Main {
    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        br.readLine();

        List<Integer> list = Stream.of(br.readLine().split(" "))
                .map(Integer::parseInt)
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());

        int alice = IntStream.range(0, list.size())
                .filter(i -> i % 2 == 0)
                .mapToObj(i -> list.get(i))
                .mapToInt(Integer::intValue)
                .sum();

        int bob = IntStream.range(0, list.size())
                .filter(i -> i % 2 == 1)
                .mapToObj(i -> list.get(i))
                .mapToInt(Integer::intValue)
                .sum();

        System.out.println(alice - bob);
    }
}

ShiftOnlyと同じ理由で、inputを使わない

ABC085B Kagami Mochi

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Collectors;

class Main {
    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int N = Integer.parseInt(br.readLine());
        long count = br.lines().limit(N).collect(Collectors.toList()).stream().distinct().count();
        System.out.println(count);

    }

}

ABC085C Otoshidama

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.stream.IntStream;

class Main {
  public static void main(String[] args) throws java.lang.Exception {

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int[] intArray = Arrays.stream(br.readLine().split(" ")).mapToInt(Integer::parseInt).toArray();
    int n = intArray[0];
    int y = intArray[1];

    IntStream.rangeClosed(0, n).forEach(ichiman -> {
      IntStream.rangeClosed(0, n -ichiman).forEach(gosen -> {
        int senen = n -ichiman -gosen;
        if(10000 *ichiman + 5000 *gosen + 1000 *senen == y) {
          System.out.println(ichiman +" " +gosen +" " +senen);
          System.exit(0);
        }
      });
    });

    System.out.println("-1 -1 -1");
  }
}

ABC049C 白昼夢 / Daydream

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.stream.Stream;

class Main {
    public static void main(String[] args) throws java.lang.Exception {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String S = br.readLine();

        long count = Stream.of(S).map(i -> i.replaceAll("eraser", "x"))
                    .map(i -> i.replaceAll("erase", "x"))
                    .map(i -> i.replaceAll("dreamer", "x"))
                    .map(i -> i.replaceAll("dream", "x"))
                    .map(i -> i.replaceAll("x", ""))
                    .filter(i -> i.equals(""))
                    .count();

        System.out.println(count > 0 ? "YES" : "NO");

    }
}

ABC086C Traveling

これ、使い所あるんですかね..

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) throws java.lang.Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int n = Integer.parseInt(br.readLine());
        List<List<Integer>> plans = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            List<Integer> plan = Stream.of(br.readLine().split(" ")).map(Integer::parseInt).collect(Collectors.toList());
            plans.add(plan);
        }

        int diff = 0;
        int nextX = 0;
        int nextY = 0;

        for (List<Integer> plan: plans) {
            diff = plan.get(0) - diff;
            nextX = plan.get(1) - nextX;
            nextY = plan.get(2) - nextY;
            int dist = Math.abs(nextX) + Math.abs(nextY);
            if (diff < dist) {
                System.out.println("No");
                return;
            } else {
                if ((diff - dist) % 2 != 0) {
                    System.out.println("No");
                    return;
                }
            }
        }

        System.out.println("Yes");

    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ビット演算の高速化メモ

はじめに

元ネタはハッカーのたのしみ(原題:Hacker's Delight)です。

ビットマップのループ

01011000
↓
f(00001000)
f(00010000)
f(01000000)

右から走査して1のときだけ処理を行いたいとき、
ビットの長さ分ループしなくても1の数のループで済ませられる。

for (int x = 0b01011000; x > 0; x &= x - 1) {
  f(x & -x);
}

このようにx & -xx &= x - 1を繰り返せば、1の部分だけ渡り歩くことができる。

x & -x

01011000 = x
10100111 = not(x)
10101000 = not(x)+1 = -x
つまり
00001000 = x & -x
となって、右端の1だけが残る。

x & x-1

01011000 = x
01010111 = x-1
つまり
01010000 = x & x-1
となって、右端の1が消える。

ビットカウント

00101110 10100000 11100101 11001011
↓
16

1の数を数えたいとき、
ビットの数だけループしなくてもlog(ビット数)回のビット演算で求められる。

x = 0b00101110101000001110010111001011;
x = (x & 0x55555555) + ((x >>>  1) & 0x55555555)
x = (x & 0x33333333) + ((x >>>  2) & 0x33333333)
x = (x & 0x0F0F0F0F) + ((x >>>  4) & 0x0F0F0F0F)
x = (x & 0x00FF00FF) + ((x >>>  8) & 0x00FF00FF)
x = (x & 0x0000FFFF) + ((x >>> 16) & 0x0000FFFF)

やっていることは、部分和をx自身に書き込んでいく分割統治。

手順

代入1回目

データを2ビットずつに区切り、2ビットごとの1の数を求めてxを上書きする。
00 10 11 10 10 10 00 00 11 10 01 01 11 00 10 11 = x

_0 _1 _2 _1 _1 _1 _0 _0 _2 _1 _1 _1 _2 _0 _1 _2(10進表現)

00 01 10 01 01 01 00 00 10 01 01 01 10 00 01 10 = 新しいx


00 10 11 10 10 10 00 00 11 10 01 01 11 00 10 11 = x
_0 _0 _1 _0 _0 _0 _0 _0 _1 _0 _1 _1 _1 _0 _0 _1 = x & 0x55555555
_0 _1 _1 _1 _1 _1 _0 _0 _1 _1 _0 _0 _1 _0 _1 _1 = ((x >>> 1) & 0x55555555)
2ビットで分けたときの上の桁、下の桁を同時に足し合わせる
00 01 10 01 01 01 00 00 10 01 01 01 10 00 01 10 = (x & 0x55555555) + ((x >>> 1) & 0x55555555)
やっていることは、2ビットのベクトル演算。

代入2回目

データを4ビットずつに区切り、4ビットごとの1の数を求めてxを上書きする。
0001 1001 0101 0000 1001 0101 1000 0110 = x

_0_1 _2_1 _1_1 _0_0 _2_1 _1_1 _2_0 _1_2(10進表現)

___1 ___3 ___2 ___0 ___3 ___2 ___2 ___3(10進表現)

0001 0011 0010 0000 0011 0010 0010 0011 = 新しいx


0001 1001 0101 0000 1001 0101 1000 0110 = x
__01 __01 __01 __00 __01 __01 __00 __10 = x & 0x33333333
__00 __10 __01 __00 __10 __01 __10 __01 = (x >>> 1) & 0x33333333
4ビットで分けたときの上の2ビット、下の2ビットを同時に足し合わせる
0001 0011 0010 0000 0011 0010 0010 0011 = (x & 0x33333333) + ((x >>> 2) & 0x33333333)
やっていることは、4ビットのベクトル演算。

代入3回目

データを8ビットずつに区切り、8ビットごとの1の数を求めてxを上書きする。
00010011 00100000 00110010 00100011 = x

___1___3 ___2___0 ___3___2 ___2___3(10進表現)

_______4 _______2 _______5 _______5(10進表現)

00000100 00000010 00000101 00000101 = 新しいx

代入4回目

データを16ビットずつに区切り、16ビットごとの1の数を求めてxを上書きする。
0000010000000010 0000010100000101 = x

_______4_______2 _______5_______5(10進表現)

_______________6 ______________10(10進表現)

0000000000000110 0000000000001010 = 新しいx

代入5回目

データ全体の1の数を求めて、xに上書きする。
0000000000000110 0000000000001010 = 新しいx

_______________6 ______________10(10進表現)

_______________________________16(10進表現)

0000000000000000 0000000000010000 = 新しいx

16

ちなみに

標準ライブラリで実装されていたりします。JavaとGoの例しか知りませんが、
Java : Integer.bitCount()、Long.bitCount()
Go : bitsパッケージのOnesCountXX()
(上記のコードよりも最適化されている)。

さらに言うと、10年前ぐらいからCPUの拡張命令(IntelであればSSE4.2のPOPCNT)としても実装されているので、
そもそも本気で高速化するなら直接POPCNTを呼べる言語を利用すべきです。

Javaに関してはJITがbitCount()をPOPCNTに置き換えてくれるらしいですが、
Goはどうなんでしょうか?

参考

wikipedia : SSE4、ハミング重み
https://en.wikipedia.org/wiki/SSE4
https://en.wikipedia.org/wiki/Hamming_weight

openjdk8のLongクラス(ソースコード)
https://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Long.java

Goのbitsパッケージ(ソースコード)
https://golang.org/src/math/bits/bits.go?s=3946:3972#L103

ビットリバース

00101110 10100000 11100101 11001011
↓
11010011 10100111 00000101 01110100

ビットを逆順にしたいときも分割統治が使える。

x = 0b00101110101000001110010111001011;
x = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >>> 16;
x = (x & 0x00FF00FF) <<  8 | (x & 0xFF00FF00) >>> 8;
x = (x & 0x0F0F0F0F) <<  4 | (x & 0xF0F0F0F0) >>> 4;
x = (x & 0x33333333) <<  2 | (x & 0xCCCCCCCC) >>> 2;
x = (x & 0x55555555) <<  1 | (x & 0xAAAAAAAA) >>> 1;

手順

代入1回目

データを16ビットずつに区切り、入れ替える。
0010111010100000 1110010111001011 = x

1110010111001011 0010111010100000 = 新しいx


0010111010100000 1110010111001011 = x
1110010111001011 ________________ = (x & 0x0000FFFF) << 16
________________ 0010111010100000 = (x & 0xFFFF0000) >>> 16
1110010111001011 0010111010100000 = (x & 0x0000FFFF) << 16 | (x & 0xFFFF0000) >>> 16

代入2回目

データを8ビットずつに区切り、隣り合う同士で入れ替える。
11100101 11001011 00101110 10100000 = x

11001011 11100101 10100000 00101110 = 新しいx


11100101 11001011 00101110 10100000 = x
11001011 ________ 10100000 ________ = (x & 0x00FF00FF) << 8
________ 11100101 ________ 00101110 = (x & 0xFF00FF00) >>> 8
11001011 11100101 10100000 00101110 = (x & 0x00FF00FF) << 8 | (x & 0xFF00FF00) >>> 8

代入3回目

データを4ビットずつに区切り、隣り合う同士で入れ替える。
1100 1011 1110 0101 1010 0000 0010 1110 = x

1011 1100 0101 1110 0000 1010 1110 0010 = 新しいx

代入4回目

データを2ビットずつに区切り、隣り合う同士で入れ替える。
10 11 11 00 01 01 11 10 00 00 10 10 11 10 00 10 = x

11 10 00 11 01 01 10 11 00 00 10 10 10 11 10 00 = 新しいx

代入5回目

データを1ビットずつに区切り、隣り合う同士で入れ替える。
1 1 1 0 0 0 1 1 0 1 0 1 1 0 1 1 0 0 0 0 1 0 1 0 1 0 1 1 1 0 0 0 = x

1 1 0 1 0 0 1 1 1 0 1 0 0 1 1 1 0 0 0 0 0 1 0 1 0 1 1 1 0 1 0 0 = 新しいx

11010011101001110000010101110100 = もとのx
00101110101000001110010111001011 = 新しいx
となって、正しく逆順になっている。

ちなみに

こちらも標準ライブラリで実装されていることがあります。
Java -> Integer.reverseBytes()、Long.reverseBytes()
Go -> bitsパッケージのReverseXX()

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Android]ShareCompatを使ってシェア(共有)する場合の画像の渡し方、コールバックの受け取り方

↓これの事

わりとたくさん情報がありそうな気がしたが、意外と出てこなかったので、メモ書き。

ライブラリ

  • com.android.support:support-compat:28.0.0

実装

SomeActivity.java
// アクティビティ内から実行する前提のコード
private void showShareChooser() {
    File tempFile = new File(getApplicationContext().getExternalCacheDir(), tempImgFilePath);

    // ファイルをシェアするためにURIを取得する場合は、FileProviderを通じて、後述するオーソリティの名前を指定して取得する必要がある
    Uri uri = FileProvider.getUriForFile(getApplicationContext()
            , getApplicationContext().getPackageName() + ".provider"
            , tempFile);

    ShareCompat.IntentBuilder builder = ShareCompat.IntentBuilder.from(this);
    builder.setChooserTitle(chooserTitle) // シェアする時のタイトル
            .setSubject(subject) // 件名。使われ方はシェアされた側のアプリによる
            .setText(text) // 本文。使われ方はシェアされた側のアプリによる
            .setStream(uri) // ファイルをシェアする時は、そのURIを指定
            .setType("image/jpeg"); // ストリームで指定したファイルのMIMEタイプ

    // URIに対する読み取り権限を付与する
    Intent intent = builder.createChooserIntent().addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

    // コールバックを受け取りたい場合は、そのインテントを使ってアクティビティを開始する
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, SNS_SHARE);
    }

    // 結果を受け取らなくても良い場合は、ビルダーからそのまま開始できる
    // builder.startChooser();
}

戻りを受け取る場合は、 通常どおり onActivityResult で受け取れる。

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case SNS_SHARE:
            // 戻りを受け取って何らか処理する
            // resultCode は必ずゼロになるので、 RESULT_OK で判定しない
            doSomething();
            break;

        default:
            super.onActivityResult(requestCode, resultCode, data);
            break;
    }
}

ファイルを共有する場合

画像などを共有する場合は、Bitmapをそのまま共有したりできないため、一旦ファイルに保存する必要がある。
また、以下のように保存先からの読み出しを許可する必要がある。

まず、パスをXMLで指定する。

src/main/res/xml/provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-cache-path name="cache" path="." />
</paths>

external-cache-path などは保存先に応じて変わる。
英語だけどFileProviderの公式リファレンスを参照。
次に、そのプロバイダを AndroidManifest.xml で指定する。

AndroidManifest.xml
<manifest
    package="com.example"
    xmlns:android="http://schemas.android.com/apk/res/android">
:
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
:
    </application>
:
</manifest>

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む