출처: http://poj.org/problem?id=2453
아시다시피, 데이터는 컴퓨터에 이진수 형태로 저장됩니다. 우리가 토론할 문제는 양의 정수와 이 수의 이진 형태입니다.
양의 정수 I가 주어지면, 당신이 할 일은 I보다 큰 수 중 가장 작은 수 J를 찾습니다. I의 이진수 형태에서의 1의 개수와 J의 이진수 형태에서의 1의 개수는 일치합니다.
예를들어, "78"이 주어지면, 여러분은 "1001110"과 같은 이진수 형태로 쓸 수 있습니다. 이 이진수는 4개의 1을 가지고 있습니다. "1001110" 보다 크고 4개의 1을 포함하는 가장 작은 정수는 "1010011"입니다. 출력값은 "83"이 되어야 합니다.
Input
각 줄에 한개의 정수를 입력할 수 있습니다. (1 <= I <= 1000000)
0이 나오면 입력을 종료합니다. 이 줄은 작업할 필요 없습니다.
Output
각 줄에 한개의 정수를 출력하면 됩니다.
Sample Input
1
2
3
4
78
0
Sample Output
2
4
5
8
83
61개의 풀이가 있습니다.
어떤 정수이든지간에 이진법으로 볼 때 다음과 같은 꼴로 나타낼 수 있죠.
xxxxxxx000111..1100...
________________^_____
이 i보다 크려면 어떻게 해야 할까요? 화살표로 표시한 가장 오른쪽에 있는 1보다 오른쪽에 1을 추가하면 어떨까요? 그러나 이렇게 하면 1의 갯수가 i보다 항상 많아집니다. 따라서 j가 될 수 없어요.
정답은 화살표 왼쪽으로 쭉 따라가다 보면 1이 아닌, 즉 0인 첫 번째 비트가 있겠죠. 0111.... 꼴일 거에요. 이걸 1을 하나 왼쪽으로 밀어서 1011....꼴으로 만들어 주고 다른 1들을 모두 오른쪽 끝으로 보내버리는 겁니다.
입력 하나당 O(1), 상수 시간에 구할 수 있습니다.
사실 제가 함수로 구현한 것들은 GCC나 VC++등에서 intrinsic으로 제공하는 오퍼레이션이기 때문에 그걸 사용하면 CPU를 사용해서 짧은 사이클 내에 더 빠르게 구할 수도 있어요.
#include<stdio.h>
size_t bit_pop_count(int number){
size_t bit_count = 0;
int i;
for(i=0;i<31;i++){
bit_count += (number >> i)&1;
}
return bit_count;
}
size_t least_significant_bit_with_one(int number){
int i;
for(i=0;i<31;i++){
if((number >> i) & 1) return i;
}
return 31;
}
int main(){
int i;
while(true){
scanf("%d", &i);
if(i == 0) break;
int cnt_ones_i = bit_pop_count(i);
int j = i + (1 << least_significant_bit_with_one(i));
int cnt_ones_j = bit_pop_count(j);
for(i=0; i < (cnt_ones_i - cnt_ones_j); ++i){
j += (1 << i);
}
printf("%d\n", j);
}
return 0;
}
파이썬입니다. 뭔가 알고리즘을 원하는거 같은데 1차원적으로 짰네요 ㅎ^^;
def getSomeNumber(a):
if a == 0:
return ""
binary_string = bin(a)[2:]
matchCount = binary_string.count('1')
while a <= 1000000:
a = a + 1
if matchCount == (bin(a)[2:]).count('1'):
break
return a
print(getSomeNumber(1))
print(getSomeNumber(2))
print(getSomeNumber(3))
print(getSomeNumber(4))
print(getSomeNumber(78))
print(getSomeNumber(0))
Java에는 포인터가 없나요? 예전에 C나 C++을 배울 땐 포인터가 있었는데... 포인터가 필요한데 포인터가 없어서.. 딱 한개짜리 배열 m[1]을 만들어서 m[0]을 썼어요 ㅋㅋㅋㅋ 좀 조잡한가요?
알고리즘:
count1f함수 파라메터로 I와 m2(1개짜리배열, 포인터 대용)를 받습니다
m2[0]에다가 I보다는 작거나 같으면서 가장 큰 2^n의 수를 집어넣습니다
(입력값 I를 연산할 때는 I는 1을 받아서 m2를 계산하고, 출력값 J를 연산할 때는 I의 m2값을 가져와서 그보다 더 큰 J의 m2가 있는지 확인합니다.)
I(혹은 J)가 2^n(=m2[0]), 2^(n-1), 2^(n-2), ..., 1 중 순서대로 각각의 수보다 클 경우 각 수를 I에서 빼는 방식으로,
I의 2진수 형태에서 1의 갯수를 count1로 계산합니다
(루프) J를 I보다 1 큰 수부터 시작하여 1씩 증가시키면서, count1f함수로 J와 m2(I의 m2)를 받을 경우 J가 I와 count1이 같은지 확인하여 같을 때까지 반복합니다.
I와 count1이 같은 J를 출력합니다.
package h_AnEasyProblem;
import java.util.Scanner;
public class AnEasyProblem {
int count1f(int I, int[] m2){
int m, count1=0;
for(m=m2[0];I/m!=0;m*=2); m2[0]=m;//m2: I>=m2, 가장 큰 2^n
for(;m>0;m/=2) if(I>=m){ I-=m; count1++;}
return count1;
}
public static void main(String[] args) {
int l,i, count1, J, N=30;
Scanner in=new Scanner(System.in);
AnEasyProblem A=new AnEasyProblem();
int[] I =new int[N]; int[] m2=new int[1];
for(l=0;l<N;l++){ I[l]=in.nextInt(); if(I[l]==0) break;}
for(i=0;i<l;i++){
m2[0]=1; count1=A.count1f(I[i], m2);
for(J=I[i]+1; A.count1f(J,m2)!=count1; J++);
System.out.print(J);
/* System.out.println(" ("+count1+")"); */
}
}
}
#입출력결과 (/* */ 부분을 풀어서 괄호 안의 1의 갯수도 출력)
1
2
3
4
7
78
83
1000000
0
2 (1)
4 (1)
5 (2)
8 (1)
11 (3)
83 (4)
85 (4)
1000064 (7)
파이썬입니다.
def easy(n):
f = lambda n:"{0:b}".format(n).count("1")
cnt = f(n)
while True:
n+=1
if f(n)==cnt:return n
for i in [1,2,3,4,78]:
print easy(i)
정수를 이진수로 바꾸는 방법으로 다음을 사용 해 봤습니다.
"{0:b}".format(n)
clojure
(defn bin-1-count [n]
(->> n
Integer/toBinaryString
(filter #{\1})
(count)))
(defn find-first [valid-fn coll]
(some #(and (valid-fn %) %) coll))
(defn an-easy-problem [n]
(let [n-1-count (bin-1-count n)]
(->> (inc n)
(iterate inc)
(find-first #(= (bin-1-count %) n-1-count)))))
(map an-easy-problem [1 2 3 4 78])
;=> (2 4 5 8 83)
[파이썬] 이진수를 거꾸로 만들어서 첫번째 1이 나오는곳에서 그 자리수 만큼 1을 더해주고 나머지는 1을 채우는 식입니다.
def AnEasy(num):
R_binary = bin(num)[2:][::-1]
cnt = R_binary.count('1')
for index,i in enumerate(R_binary) :
if i =="1" :
n = bin(num + (2**index))[2:]
sub = cnt - n.count('1')
return int(n,2)+(2**sub)-1
return "fail"
print(AnEasy(1))
print(AnEasy(2))
print(AnEasy(3))
print(AnEasy(4))
print(AnEasy(78))
print(AnEasy(0))
파이썬입니다. 파이썬을 배운지 이틀밖에 되지 않아 bin 함수가 있는 줄 모르고 하나 만들었네요.
def easy(n):
i=n+1
while True:
if (binary(i,[]).count(1) == binary(n,[]).count(1)):
print i
return
i+=1
def binary(n, list):
while True:
list.insert(0,n%2)
if n/2 == 0:
return list
else:
return binary(n/2,list)
input_list=[]
while True:
foo = input('Enter Value: ')
if foo!=0:
input_list.append(foo)
else:
break
for n in input_list:
easy(n)
def find(aaa):
bbb=''
for i in range(len(aaa)):
if aaa[-i]=='1':
for k in range(i,len(aaa)):
if aaa[-k]=='0':
if k>2:
bbb+=aaa[:-k]+'10'+aaa[-k+2:]
else:
bbb+=aaa[:-k]+'10'
return bbb
print(find(aa))
공부어렵네요 ㅠㅠㅠㅠ 루프가 두개돌아가는것같지만 실질적으로는 하나돌아간답니다
예제의 숫자가 작아서 그냥 루프돌려 버렸습니다.
def next_number(i)
s = i.to_s(2)
count = s.count("1")
loop do
i += 1
break if count == i.to_s(2).count("1")
end
i
end
next_number(1)
next_number(2)
next_number(3)
next_number(4)
next_number(78)
C#으로 작성했습니다. 김재주님께서 올리신 풀이를 보고 풀었는데, 솔직히 왜 이렇게 되는지 아직도 그 이유를 모르겠네요. 풀이 보면서, 리서치 해가면서 어렵사리 풀었습니다.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace CodingDojang
{
class CodingDojang
{
static void Main(string[] args)
{
AnEasyProblem.Answer();
}
}
public class AnEasyProblem
{
public static void Answer()
{
var dummy = 0;
List<int> inputs = new List<int>();
while(dummy == 0)
{
var input = int.Parse(Console.ReadLine().ToString());
if (input == 0)
break;
inputs.Add(input);
}
foreach (var input in inputs)
Console.WriteLine(AnEasyProblem(input));
}
public static string AnEasyProblem(int input)
{
var binary = "0" + Convert.ToString(input, 2);
var array = binary.ToCharArray();
Array.Reverse(array);
var reverse = new string(array);
var first = reverse.Substring(0, reverse.IndexOf("10"));
array = first.ToCharArray();
array = array.OrderByDescending(a => a).ToArray();
first = new string(array);
var second = reverse.Substring(reverse.IndexOf("10"));
var regex = new Regex(Regex.Escape("10"));
var replace = regex.Replace(second, "01", 1);
reverse = first + replace;
array = reverse.ToCharArray();
Array.Reverse(array);
var answer = new string(array);
return Convert.ToInt32(answer, 2).ToString();
}
}
}
int ByOnes(int input)
{
int count = 0;
while (input > 0)
{
count += input % 2;
input /= 2;
}
return count;
}
void exce48()
{
int *arr, n = 0, input;
arr = (int *)malloc(sizeof(int));
while (1)
{
scanf_s("%d", &input);
if (input == 0)
break;
else
{
n++;
arr = (int *)realloc(arr, sizeof(int) * n);
arr[n - 1] = input;
}
}
for (int i = 0; i < n; i++)
{
int temp = arr[i]+1;
while (ByOnes(arr[i]) != ByOnes(temp))
{
temp++;
}
printf("%d\n", temp);
}
}
2진수로 변환했을떄 1의 갯수를 세는 함수를 만들어서 풀었습니다.
알고리즘 따위는 없따아아아!!
l =[]
while 1:
n = eval(raw_input())
if n==0:break
l.append(n)
print
for n in l:
nof1=bin(n).count('1')
n+=1
while nof1 != bin(n).count('1'):n+=1
print n
n = input("input a number:")
i = n+1
while list(str(bin(n))).count('1') != list(str(bin(i))).count('1'):
i+=1
print i
Ruby
ones = ->n { n.digits(2).count(1) }
to_j = ->n,cnt=ones[n] { _ until ones[n+=1] == cnt; n }
find_j = -> { *nums,_ = gets('0').split.map &:to_i; puts nums.map &to_j }
Test
$stdin = StringIO.new("1\n2\n3\n4\n78\n0\n")
result = "2\n4\n5\n8\n83\n"
expect{ find_j.call }.to output(result).to_stdout
파이썬입니다. 뭔가 함정이 있는 문제인줄 알았는데.... 아닌가보네요.
def do(x):
c = bin(x).count('1')
y = x + 1
while True:
if bin(y).count('1') == c:
print(y)
return
y += 1
data = []
while True:
x = int(input())
if x > 0:
data.append(x)
else:
break
for i in data:
do(i)
def f(x):
if len(x) == 3:
return x+'0'
a = x[2:]
b = x[3:]
c = list((m, n) for m, n in zip(a,b))
c.reverse()
for i, (m, n) in enumerate(c):
if n == '1' and m == '0':
x = x[:len(x)-1-i]+'0'+x[len(x)-i:]
x = x[:len(x)-1-(i+1)]+'1'+x[len(x)-(i+1):]
if i!=0:
x = x[:len(x)-i]+(x[len(x)-i:])[::-1]
return x
else:
return '0b1'+'0'*x.count('0')+'1'*(x.count('1')-1)
while __name__ == '__main__':
inpt = []
while 1:
inpt.append(bin(int(input('>>>'))))
if inpt[-1] == bin(0):
inpt.pop(-1)
break
for x in inpt:
print(int(f(x), base = 2))
되게 헷갈리네요;; 파이썬 3.5.1
target = 78
num = target
target_len = bin(target).count('1')
while True:
num += 1
temp_len = bin(num).count('1')
if temp_len == target_len :
print(bin(num),num)
break
#include <stdio.h>
#include <stdlib.h>
int get1N(int n);
void main() {
int input = 0;
while(input!=-1) {
scanf("%d", &input);
int temp = input+1;
while(get1N(input) != get1N(temp)) {
temp++;
}
printf("=>%d\n", temp);
}
}
int get1N(int n) {
int r = 0;
while(n!=0) {
if(1==1&n)
r++;
n = n>>1;
}
return r;
}
def func(num):
count, step = list(bin(num)[2:]).count('1'), 1
while True:
if list(bin(num+step)[2:]).count('1') == count:
return num+step
step += 1
for x in [1,2,3,4,78]:
print(func(x))
#### 2017.01.27 D-391 ####
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import static java.lang.System.in;
public class AnEasyProblem {
public static void main(String[] args) {
Scanner sc = new Scanner(in);
List<Integer> l = new ArrayList<>();
while (sc.hasNext()) {
int s1 = sc.nextInt();
if (s1 == 0) {
break;
}
l.add(s1);
}
for (int k = 0; k < l.size(); k++) {
int a = l.get(k);
int b = Integer.bitCount(a);
for (int j = a + 1; j <= 1000000; j++) {
if (Integer.bitCount(j) == b) {
System.out.println(j);
break;
}
}
}
}
}
Integer.bitCount() 메서드 때문에 날로 먹는거 같네요 ㅡ_ㅡ;;
def f_bin(n):
if n==0: return false
count_one = str(bin(n))[2:].count("1")
while (n):
n += 1
answer = str(bin(n))[2:].count("1")
if count_one == answer:
return n
data = []
while True:
x = int(input())
if x > 0:
data.append(x)
else:
break
for i in data:
print f_bin(i)
아이디어
정규식으로 풀어보았습니다.
일단 xxxxxx01111100000 이런식의 이진수일 때,
- 오른쪽 끝에 있는 제일 첫번째 1을 왼쪽으로 한 칸 옮기고
- 나머지 1들을 오른쪽으로 쉬프트해야 됩니다.
이것을 정규식으로 풀기 위해 다음과 같이 해봤습니다.
고려해야 할 것은 111110000 과 같이 자릿수가 하나 더 늘어나야 하는 경우입니다.
그래서 제일 높은자리 왼쪽에 먼저 0으로 채워놓고 시작합니다. (111110000 -> 0111110000)
1. 2진수의 제일 왼쪽에 0을 추가해줍니다. 그러면 0111, 0100100 등으로 되겠지요.
2. 정규식으로 01(1*)(0*)$ 를 검사합니다. (제일 마지막에 등장하는 0111110000 에 매칭됨)
3. 첫번째의 01 은 10으로 바뀌면 됩니다 (1번에서 0을 추가했기 때문에 1, 111, 의 경우도 커버가 됩니다. 01, 0111 등으로 변해있기 때문)
4. (1*)와 (0*)의 자리를 바꾸어 줍니다.
5. 3, 4에서 한 것이 첫번째 1은 왼쪽으로 한 칸, 나머지 1들은 오른쪽으로 다 미는 것이지요.
6. 다시 10진수로 바꿀 때 제일 첫 자리의 0은 무시됩니다
끝.
javascript(ES6)
var easy = function(input) {
var list = input.split("\n").map(v => parseInt(v));
return list.slice(0, list.indexOf(0)).map(getNext);
};
var getNext = function(n) {
return parseInt(("0" + n.toString(2)).replace(/01(1*)(0*)$/g, "10$2$1"), 2);
};
var input= `1
2
3
4
78
0`;
console.log(easy(input).join("\n"));
Python
'01'이 있으면 자릿수를 유지합니다. 마지막으로 나타난 '01'을 '10'으로 바꾸고, 그 뒷부분을 arrange합니다.
'01'이 없으면 '1111111' 이나 '11111000' 같은 숫자인데, 자릿수를 하나 늘리는 수밖에 없습니다.
첫 '1'을 제외하고, '0'을 하나 덧붙여서 arrange합니다.
# 2진수 -> 10진수
def btod(b):
return 0 if not b else 2 * btod(b[:-1]) + int(b[-1])
# 10진수 -> 2진수. bin()으로 대체 가능(bin()은 0bxxxxx로 리턴해줌)
def dtob(d):
return '' if d==0 else dtob(d // 2) + str(d % 2)
# b에서 '0'을 앞으로, '1'을 뒤로 이동
def arrange(b):
return '0' * b.count('0') + '1' * b.count('1')
def findJ(I):
b = dtob(I)
p = b.rfind('01')
if p >= 0:
return b[:p] + '10' + arrange(b[p+2:])
else:
return b[0] + arrange(b[1:] + '0')
inp = [1, 2, 3, 4, 78]
for I in inp:
print(btod(findJ(I)))
C#: Python 코드 그대로 옮겼습니다.
using System.Linq;
using static System.Console;
class AnEasyProblem
{
public static string dtob(int i) => i == 0 ? "" : dtob(i / 2) + (i % 2).ToString();
public static int btod(string b, int i) => i < 0 ? 0 : 2 * btod(b, i-1) + (b[i] - '0');
public static string arrange(string b)
{
string zeros = "", ones = "";
for (int i = 0; i < b.Count(c => c == '0'); i++)
{
zeros = zeros + '0';
}
for (int i = 0; i < b.Count(c => c == '1'); i++)
{
ones = ones + '1';
}
return zeros + ones;
}
public static string findJ(int I)
{
string b = dtob(I);
int p = -1;
for (int i = b.Length - 2; i > 0; i--)
{
if (b[i] == '0' && b[i+1] == '1')
{
p = i;
break;
}
}
if (p >= 0)
{
return b.Substring(0, p) + "10" + arrange(b.Substring(p + 2));
}
else
{
return b[0] + arrange(b.Substring(1) + "0");
}
}
static void Main(string[] args)
{
int[] inp = new int[] { 1, 2, 3, 4, 78 };
foreach (int I in inp)
{
string b = findJ(I);
WriteLine(btod(b, b.Length - 1));
}
}
}
def getBenNext(n):
s_1_cnt = str(bin(n)).count('1')
while True:
n = n + 1
if s_1_cnt == str(bin(n)).count('1'):
print(n)
break
while True:
num = input('각 줄에 한개의 정수를 입력할 수 있습니다. (1 <= I <= 1000000) : ')
if num == '' or int(num) == 0 or int(num)>1000000:
break
getBenNext(int(num))
package codingdojang;
import java.util.Scanner;
public class ex48 {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int a = sc.nextInt(); sc.nextLine();
int b = Integer.bitCount(a);
int result = a;
System.out.println(b);
if(a==0) return;
for (int i = a+1; b != Integer.bitCount(i); i++) {
result = i;
}
result++;
System.out.println(Integer.bitCount(result));
System.out.println(result);
}
}
파이썬 3.6
def bin_count(num):
data = []
while num//2 != 0:
data.append(str(num%2))
num = num//2
data.append(str(num%2))
data.reverse()
return data.count('1')
def bigger(num):
count ,tmp, big = bin_count(num), 0, num
while tmp != count:
big += 1
tmp = bin_count(big)
print(big)
if __name__ == "__main__":
num = int(input("num = "))
bigger(num)
*결과값
num = 2
4
num = 4
8
num = 78
83
r로 풀었습니다. 2진수로 나타냈을 때 1이 들어가는 자릿수를 벡터 변수에 넣고(예: 78의 경우 6,3,2,1), 이 벡터 변수의 길이를 세어(4), 원래 숫자에서 1씩 더하면서 같은 방식으로 벡터 변수를 만들고 비교하여 같은 값이 나오면 출력되게끔 만들었습니다.
```{r}
f1<-function(...){
a<-c(...)
if(a[length(a)]==0){
k<-rep(0, (length(a)-1))
for(b in 1:(length(a)-1)){
x<-a[b]; x0<-x; v<-NULL; u<-NULL; i<-1; j<-1
repeat{
repeat{
v[i]<-trunc(log2(x0))
x0<-x0-2**v[i]
if(x0==0){
break }
i<-i+1 }
i<-1; u[j]<-length(v); x0<-x+j
if(length(u)>1){
if(u[j]==u[1]){
break
}else{
v<-NULL } }
j<-j+1 }
for(n in v){
k[b]<-k[b]+2**n
} } }
for(b in 1:(length(a)-1)){
print(k[b]) } }
f1(1,2,3,4,78,0)
```
def easy(n):
a = bin(n)
if '01' in a:
b = len(a)-a[::-1].index('10')-2
return int(a[:b]+'10'+'0'*(a[b+2:].count('0'))+'1'*(a[b+2:].count('1')), 2)
else:
return int('0b1'+'0'*(a.count('0'))+'1'*(a.count('1')-1), 2)
def easy(n):
if n==0: return""
re=[]
m=n
while (m>=1):
re+=[m%2]
m=m//2
re+=[0]
ind10=re[re.index(1):].index(0)+re.index(1)
re[0:ind10+1]=[1 for i in range(re[0:ind10].count(1)-1)]+[0 for i in range(ind10-re[0:ind10].count(1)+1)]+[1]
return sum([(2**i)*re[i] for i in range(len(re))])
#include <stdio.h>
int main() {
int n, i, ind1, ind10, mul2=1;
int re[100];
while (1) {
mul2 = 1;
printf("숫자를 입력하시오.\n");
scanf_s("%d", &n);
for (i = 0; i < 100; i++) {
re[i] = n % 2;
n = n / 2;
if (n == 0) {
re[i + 1] = 0;
re[i + 2] = 0;
break;
}
}
for (ind1 = 0; ind1 < i + 1; ind1++) {
if (re[ind1] == 1) {
break;
}
}
for (ind10 = ind1; ind10 < i+1; ind10++) {
if (re[ind10] == 0) {
break;
}
}
for (int j = 0; j < ind10; j++) {
re[j] = (j >= ind10 - ind1 - 1 ? 0 : 1);
}
re[ind10] = 1;
for (int j = 0; j <=i + 1; j++) {
re[i + 2] += mul2 * re[j];
mul2 *= 2;
}
if (ind1 == i + 1) {
printf(" ");
}
else {
printf("%d\n", re[i + 2]);
}
}
return 0;
}
import java.util.Scanner;
public class AnEasyProblem {
public static int checker(int number){
String strNumber = Integer.toBinaryString(number);
int oneCount = 0;
for(int i=0; i< strNumber.length(); i++){
if(strNumber.charAt(i) == '1'){
oneCount++;
}
}
return oneCount;
}
public static void execute(int number){
String strNumber = Integer.toBinaryString(number);
int oneCount = 0;
for(int i=0; i< strNumber.length(); i++){
if(strNumber.charAt(i) == '1'){
oneCount++;
}
}
int result = 0;
while(result != oneCount){
result = checker(++number);
}
System.out.println(number);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
while(true){
String input = sc.nextLine();
if(input.trim().equals("0")){
break;
}
int number = Integer.parseInt(input);
execute(number);
}
}
}
function count (x) {
return x.toString(2).split("").reduce((acc,item) => acc + parseInt(item) , 0)
}
function upper (x) {
let i = 1
while (count(x) !== count(x+i)) {
i++
}
return x+i
}
```{.java} public int nextBigNumber(int n) { int answer = 0; String num = Integer.toBinaryString(n); int count = 0; int count2 = 0; for (int i=0; i<num.length(); i++) { if(num.charAt(i) == '1') count++; } String num2 = ""; for (int i=n+1; i<999999999; i++) { num2 = Integer.toBinaryString(i); for (int j=0; j<num2.length(); j++) { if(num2.charAt(j) == '1') count2++; } if (count == count2) { break; } count2 = 0; }
answer = Integer.parseInt(num2, 2);
return answer;
}
```// 자바입니다
```{.java} public int nextBigNumber(int n) { int answer = 0; String num = Integer.toBinaryString(n); int count = 0; int count2 = 0; for (int i=0; i<num.length(); i++) { if(num.charAt(i) == '1') count++; } String num2 = ""; for (int i=n+1; i<999999999; i++) { num2 = Integer.toBinaryString(i); for (int j=0; j<num2.length(); j++) { if(num2.charAt(j) == '1') count2++; } if (count == count2) { break; } count2 = 0; }
answer = Integer.parseInt(num2, 2);
return answer;
}
```// 자바입니다
public int nextBigNumber(int n) {
int answer = 0;
String num = Integer.toBinaryString(n);
int count = 0;
int count2 = 0;
for (int i=0; i<num.length(); i++) {
if(num.charAt(i) == '1')
count++;
}
String num2 = "";
for (int i=n+1; i<999999999; i++) {
num2 = Integer.toBinaryString(i);
for (int j=0; j<num2.length(); j++) {
if(num2.charAt(j) == '1')
count2++;
}
if (count == count2) {
break;
}
count2 = 0;
}
answer = Integer.parseInt(num2, 2);
return answer;
}
```// 자바입니다```{.java}
public int nextBigNumber(int n) {
int answer = 0;
String num = Integer.toBinaryString(n);
int count = 0;
int count2 = 0;
for (int i=0; i<num.length(); i++) {
if(num.charAt(i) == '1')
count++;
}
String num2 = "";
for (int i=n+1; i<999999999; i++) {
num2 = Integer.toBinaryString(i);
for (int j=0; j<num2.length(); j++) {
if(num2.charAt(j) == '1')
count2++;
}
if (count == count2) {
break;
}
count2 = 0;
}
answer = Integer.parseInt(num2, 2);
return answer;
} //자바입니다
import java.text.*;
import java.util.*;
public class Main {
static int cons=0;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int count=0;
while(true) {
System.out.println("몫을 입력하세요.");
cons=Integer.parseInt(sc.nextLine());
if(cons==0) {
System.out.println("종료.");
System.exit(0);
}
count=leftovers(cons);
while(leftovers(++cons)!=count) {
}
System.out.println(cons);
}
}
private static int leftovers(int cons) {
while(true) {
int count=0;
int num=cons;
StringBuilder left_overs=new StringBuilder();
int left=0;
while(num!=1) {
left=num%2;
num=num/2;
left_overs.append(left);
}
left_overs.append(num);
left_overs.reverse();
String str=new String(left_overs.toString());
String[] str_left=str.split("(?!^)");
for(int i=0;i<str_left.length;i++) {
if(str_left[i].equals("1")) {
count++;
}
}
return count;
}
}
}
Python 막무가내식 풀이네요..
while True:
a = int(input())
if a == 0:
break
n = str(bin(a)[2:]).count("1")
while True:
a += 1
if str(bin(a)[2:]).count("1") == n:
break
print(a)
def easyp(n):
endp,tmp = 0,n
while tmp%2 == 0:
endp += 1; tmp >>= 1
stap = endp
while tmp%2 == 1:
stap += 1; tmp >>= 1
return (tmp+1 << stap) + ((n-(tmp << stap) - (1 << (stap-1))) >> endp)
n = []
print('input')
while 1:
n.append(int(input()))
if n[-1] == 0: n.pop(); break
print('output')
for i in n: print(easyp(i))
저는 python을 사용하였습니다. binary로 나타낸 후 부분에 대하여 세 그룹으로 나누었습니다. 2^0 의 자리부터 읽었을 때 연속한 0을 g1, 연속한 1을 g2, 그리고 나서 등장하는 0을 g3라 하였습니다. binary의 첫자리가 1인 경우에만 리스트를 확장해주었습니다.
def DtoB(a, b): # a엔 deci가, b엔 빈 리스트가 들어감.
while a>0:
if a%2 == 0:
b.append(0)
a = a/2
else:
b.append(1)
a = (a-1)/2
return DtoB(a, b)
return b
def BtoD(a):
D = 0
n = len(a)
for i in range(n):
D += a[i]*(2**i)
return D
I = int(input("put number"))
IB = DtoB(I, [])
# 00..0/11..1/0 g1, g2, g3
lenI = len(IB) # 처음 나오는 1의 index를 반환하자.
g2_0 = IB.index(1) # g2의 처음 index
sub = list() # g3_0 반환 위해서
for i in range(g2_0, lenI):
sub.append(IB[i])
JB = list()
for i in range(lenI):
JB.append(IB[i])
if 0 in sub: # g3의 처음 index
g3_0 = sub.index(0) + g2_0
JB[g3_0] = 1
else:
g3_0 = int(lenI)
JB.append(1)
num1 = g3_0 - g2_0
for i in range(g3_0):
JB[i] = 0
for j in range(num1-1):
JB[j] = 1
J = BtoD(JB)
print(J)
def convertTobinary(t_num):
result=''
while t_num != 1: # t_num은 나머지값을 저장할 것.
result+=str(t_num%2)
t_num=t_num//2
result+=str(t_num)
return result[::-1]
def convertTointeger(b_num):
cir=1
result=0
for i in b_num[::-1]:
result+= (int(i)*cir)
cir*=2
return result
def AEP():
input_value = int(input())
input_binary = convertTobinary(input_value)
idx = input_binary.find('01')
str_result=''
if idx == -1: # 01 패턴이 발견되지 않았다면, 입력 패턴은 111100000 이렇게되어 있을것. 이때는 자리수를 늘려야 된다.
str_result +='1'
for i in range(len(input_binary)-input_binary.count('1')+1):
str_result +='0'
str_result +='1'*(input_binary.count('1')-1)
else:
str_result = input_binary[:idx] + '1'
for i in range(len(input_binary[(idx+1):])-input_binary[(idx+1):].count('1')+1):
str_result +='0'
str_result +='1'*(input_binary[(idx+1):].count('1')-1)
print(convertTointeger(str_result))
AEP()
C#
using System;
using System.Linq;
namespace CD048
{
class Program
{
static void Main()
{
string result = String.Empty;
while (true)
{
int input = int.Parse(Console.ReadLine());
if (input == 0) { break; }
result += NextValue(input).ToString() + Environment.NewLine;
}
Console.WriteLine(result);
}
static int NextValue(int aNumber)
{
int oneCount = CountOne(aNumber);
while (oneCount != CountOne(++aNumber)) { }
return aNumber;
}
static int CountOne(int aNumber) => Convert.ToString(aNumber, 2).Count(b => b == '1');
}
}
def numTobinary(num):
num = num
max_i = 0
while num >= 2 ** max_i:
max_i += 1
max_i -= 1
to_binary = ''
# num 을 다 채울때까지 이진수 빼기를 수행한다.
for i in range(max_i, -1, -1):
if num >= 2 ** i:
to_binary += '1'
num = num - (2 ** i)
else : to_binary += '0'
return to_binary
is_continue = True
while is_continue:
num = int(input())
if num != 0:
near_up_num = num + 1
while numTobinary(num).count('1') != numTobinary(near_up_num).count('1'):
near_up_num += 1
print(near_up_num)
else : is_continue = False
def Easy_Problem(num):
this = num + 1
count = bin(num).count('1')
while bin(this).count('1') != count:
this += 1
return this
got = [1]
while got[-1] != 0:
got.append(int(input()))
del got[-1], got[0]
for change in got:
print(Easy_Problem(change))
def binar(n):
cnt,n = bin(n)[2:].count('1'),n+1
while bin(n)[2:].count('1') != cnt:
n += 1
return n
가장 단순한 방법으로;; 그런데 실질적으로 속도에 큰 차이는 없더군요.
def binone(n):
count=0
while n>0:
if n%2==1:
n=n-1
count+=1
else:
n=n//2
return count
def binnext(n):
k=n+1
while True:
if binone(k)==binone(n): break
else: k+=1
return k
original=[]
while True:
user=int(input("Input positive integers (input '0' to stop inputting): "))
if user!=0:
original.append(user)
else: break
for i in original:
print(binnext(i))
import java.util.Scanner;
public class AnEasyProblem {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("숫자 입력 : ");
int n = scanner.nextInt();
String binum = Integer.toBinaryString(n);
int i = 1; // 2진수 1의개수 찾기
int count1 = 0;
while(true) {
if(binum.substring(binum.length() - i, binum.length() - i + 1).equals("1")) {
count1++;
};
if(i == binum.length()) break;
i++;
}
int count2 = 0; // 값 찾기
String s = "";
for(int j = n + 1; ; j++) {
s = Integer.toBinaryString(j);
i = 1;
count2 = 0;
while(true) {
if(s.substring(s.length() - i, s.length() - i + 1).equals("1")) {
count2++;
};
if(i == s.length()) break;
i++;
}
if(count1 == count2) break;
}
int x = 0, y = 1; // 2진수 10진수로 변환
i = 1;
while(true) {
x += Integer.parseInt(s.substring(s.length() - i, s.length() - i + 1)) * y;
y *= 2;
if(i == s.length()) break;
i++;
}
System.out.println(x);
}
}
def find(n):
ans = bin(n).count('1')
while True:
n += 1
if bin(n).count('1') == ans:
print(n)
return
비트연산자로 좀 더 깔끔하게 구하는 방법은 없을까요..ㅠㅠ
#include<stdio.h>
long long int n;
int main()
{
int i, j, k;
while (1) {
scanf("%lld", &n);
if (n == 0)break;
for (i = 0; i < 63; i++)if (n & (1 << i))break;
j = i;
for (; i < 63; i++)if (!(n & (1 << i)))break;
k = i - j;
n >>= i;
n |= 1;
n <<= i;
n |= ((1 << (k-1)) - 1);
printf("%lld\n", n);
}
}
inp = int(input("INPUT : "))
n, inp_c = 1, str(bin(inp)[2:]).count('1')
print(inp, "(%s)" % bin(inp)[2:])
while True :
if str(bin(inp+n)[2:]).count('1') == inp_c :
print("OUTPUT : ", inp+n, "(%s)" % bin(inp+n)[2:])
break
else :
n += 1
저도 계산속도가 그렇게 느릴 것 같지는 않아서 그냥 루프 돌렸습니다
결과
INPUT : 412678
412678 (1100100110000000110)
OUTPUT : 412681 (1100100110000001001)
def binary(num):
count=0
while num>0:
if num%2!=0:
count+=1
num=num//2
return count
num=int(input("정수 입력 : "))
a=num+1
count=binary(num)
while True:
if count==binary(a):
print(a)
break
a+=1
def easy(inp):
total = len(format(inp, 'b'))
one = format(inp, 'b').count('1')
for n in range(inp+1, int('0b'+('1'*total), 2)+1):
temp = format(n, 'b').count('1')
if temp == one:
print(n)
break
if __name__ == '__main__':
inp = 78
easy(inp)
a = int(input())
if a == 0:
print('답없음')
else:
bit = format(a,'b')
countone = bit.count('1')
answer = a+1
while answer > a:
if format(answer,'b').count('1') == countone:
print(answer)
break
else:
answer += 1
def bignumber(a) :
bi_a = bin(a)
one = str(bi_a).count('1')
bi_b = bi_a
while True :
b = int(bi_b, 2) + 1
bi_b = bin(b)
b_one = str(bi_b).count('1')
if b_one == one :
b = int(bi_b, 2)
break
else :
continue
return b
while True :
a = int(input())
if a == 0 :
break
else :
print(bignumber(a))
def Problem(a):
if a==0:
exit()
b = str(bin(a)).count('1')
while True:
a=a+1
if str(bin(a)).count('1')==b:
print(a)
break
Problem(int(input("숫자 입력 : ")))
값을 각각 대입하는 기초적인 방법을 썼습니다. 그래도 실행 속도가 크게 떨어지지는 않네요. 소스 코드입니다.
def get_j(i: int) -> int:
i_bin = '0' + (bin(i)[2:])
j = i + 1
while bin(j)[2:].count('1') != i_bin.count('1'): j += 1
return j
i_list = []
while True:
INPUT = int(input())
if INPUT: i_list.append(INPUT)
else: break
print()
for i in i_list:
print(get_j(i))
실행 결과입니다.
1
2
3
4
78
0
2
4
5
8
83
from math import *
#입력 받은 수를 이진수로 변환한뒤, 1의 개수를 cnt하는함수
def cnt1(n):
a = bin(n)[2:]
return a.count('1')
#입력받은수보다 1씩 수를 증가시키면서 이진수로 변환한뒤 1의 개수가 같은 수를 찾는 함수
def fun (n):
k=n+1
while cnt1(k)!=cnt1(n):
k+=1
return k
arr = []
while True:
inp = int(input("정수를 입력하시오"))
if inp==0:
break
else:
arr.append(inp)
for i in arr:
print(fun(i))
math 라이브러리에서 이진수 변환 함수 'bin'을 이용했어요~
import java.util.Scanner;
import java.util.LinkedList;
import java.util.ListIterator;
public class AnEasyProblem48 {
static LinkedList<Integer> list;
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
AnEasyProblem48 problem = new AnEasyProblem48();
while(true) {
System.out.print("$ Input: ");
int inputNumber = scan.nextInt();
// ** Exception
if(inputNumber == 0) {
break;
}else if(inputNumber<1 || inputNumber>1000000) {
System.out.println("Out of bounds.");
continue;
}
// ** Get binary of inputNumber & print binary.
list = new LinkedList<>();
ListIterator iterInput = problem.getBinary(inputNumber);
problem.printBinary(iterInput, "Binary of input number");
// ** Get result & print binary.
problem.findOutput(iterInput);
problem.printBinary(iterInput, "Binary of output number");
problem.printDecimal(iterInput);
}
scan.close();
System.exit(0);
}
// ** Get binary of input number.
private ListIterator getBinary(int inputNumber) {
ListIterator iter = list.listIterator();
int remainder = 0;
while(inputNumber > 0) {
remainder = inputNumber%2;
inputNumber /= 2;
if(list.size()!=0)
iter.previous();
iter.add(remainder);
}
moveFirstPosition(iter);
return iter;
}
// ** Print binary.
private void printBinary(ListIterator iter, String contents) {
moveFirstPosition(iter);
System.out.printf("%s: ", contents);
while(iter.hasNext()) {
System.out.print(iter.next());
}
System.out.println();
}
// ** Find a binary of output.
private void findOutput(ListIterator iter) {
int oneOfInput = getNumberOne(iter);
int oneOfOutput = 0;
while(oneOfOutput != oneOfInput) {
moveLastPosition(iter);
int units = (int)iter.previous() + 1;
iter.set(units);
editBinary(iter);
oneOfOutput = getNumberOne(iter);
}
}
// ** Get number of one.
private int getNumberOne(ListIterator iter) {
moveFirstPosition(iter);
int count = 0;
while(iter.hasNext()) {
if((int)iter.next()==1)
count++;
}
return count;
}
// ** Move the position to the front of the first node.
private void moveFirstPosition(ListIterator iter) {
while(iter.hasPrevious()) {
iter.previous();
}
}
// ** Move the position to the next of the last node.
private void moveLastPosition(ListIterator iter) {
while(iter.hasNext()) {
iter.next();
}
}
// ** Edit binary.
private void editBinary(ListIterator iter) {
moveLastPosition(iter);
while(iter.hasPrevious()) {
int currentNode = (int)iter.previous();
if(iter.nextIndex()!=list.size()-1) {
currentNode += 1;
}
if(currentNode == 2) {
iter.set(0);
if(iter.nextIndex()==0) {
iter.add(1);
return;
}
}else {
iter.set(currentNode);
return;
}
}
}
// ** Print the result in decimal notation.
private void printDecimal(ListIterator iter) {
moveLastPosition(iter);
int multi = 1;
int result = 0;
while(iter.hasPrevious()) {
result += (int)iter.previous()*multi;
multi *= 2;
}
System.out.printf("Output : %d\n", result);
}
}
List로 풀어보았습니다.
def nextSu(N):
bN = bin(N)[2:]
ones, zeros = 0, 0
idx = len(bN)-1
while idx >= 0 and True:
if bN[idx]=='1':
ones += 1
else:
zeros += 1
if ones > 0:
break
idx -= 1
res = bN[:len(bN)-ones-zeros] + '1'
if zeros==0 and ones>1:
zeros=1
res += '0'*zeros + '1'*(ones-1)
if ones==1:
res += '0'
return int('0b'+res, 2)
print(nextSu(1))
print(nextSu(2))
print(nextSu(3))
print(nextSu(78))
JAVA입니다.
package question4.an_easy_problem;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
List<Integer> inputs = new ArrayList<Integer>();
Scanner sc = new Scanner(System.in);
while(true) {
int next = sc.nextInt();
if(next == 0) {
break;
}
inputs.add(next);
}
sc.close();
for (Integer integer : inputs) {
System.out.println(getMinLarger(integer));
}
}
static int getMinLarger(int i) {
String binary = Integer.toBinaryString(i);
int minOneIndex = binary.indexOf('1', 1);
int maxZeroIndexBeforeOne = binary.lastIndexOf('0', minOneIndex);
if(maxZeroIndexBeforeOne == -1) {
binary = "0" + binary;
maxZeroIndexBeforeOne = 0;
minOneIndex = binary.indexOf('1', 1);
}
if(minOneIndex == -1) {
binary = "0" + binary;
minOneIndex = 1;
maxZeroIndexBeforeOne = 0;
}
char[] binaryChars = binary.toCharArray();
binaryChars[minOneIndex] = '0';
binaryChars[maxZeroIndexBeforeOne] = '1';
String partialBinary = String.copyValueOf(binaryChars);
String headBinary = partialBinary.substring(0, minOneIndex+1);
String tailBinary = getPartialMin(partialBinary.substring(minOneIndex+1));
return Integer.parseInt(headBinary + tailBinary, 2);
}
static String getPartialMin(String part) {
char[] partChars = part.toCharArray();
String minStr = "";
for (char c : partChars) {
if(c == '1') {
minStr = minStr + "1";
}
else {
minStr = "0" + minStr;
}
}
return minStr;
}
}