출처: https://brunch.co.kr/@sunghokimnxag/5
일련의 숫자가 있고, 이 숫자는 1씩 증가, 또는 감소한다. n번째의 숫자가 있을 시에, 이 숫자가 7의 배수(7, 14, 21,...)거나 7이란 숫자를 포함할 시에 (7, 17, 27,...) 방향을 바꾼다.
즉, 다음과 같이 숫자는 진행한다.
1,2,3,4,5,6,[7],6,5,4,3,2,1,[0],1,2,[3],2,1,0,[-1],0,1
(첫 번째 7은 7번째, 두번째 0은 14번째, 세번째 3은 17번째, 네번째 -1은 21번째)
이와 같은 pingpong(x)의 함수를 작성하라. 예시의 인풋과 아웃풋은 다음과 같다.
pingpong(8) = 6
pingpong(22) = 0
pingpong(68) = 2
pingpong(100) = 2
심화학습
위 문제에 다음과 같은 제약을 추가하여 다시 풀어보자.
47개의 풀이가 있습니다.
Ruby
3가지로 품. ( list조작 + 문자열, list 조작 + 문자열 사용않기, recursion + 아무것도 사용않기)
string, list comprehension - 쉽게 풀기
sevens = ->nth { (0..nth).select {|n| n%7==0 || n.to_s.include?("7") || n==nth} }
pingpong = ->x { sevens.(x).each_cons(2).map {|a,b| b-a }.map.with_index.
reduce(0) {|sum,(gap,i)| sum + gap*(i.odd?? -1:1)} }
# test
expect( [8,22,68,100,10000,100000].map &pingpong ).to eq [6, 0, 2, 2, -122, 212]
expect( Benchmark.realtime { pingpong.(100000) } ).to be_between(0.001, 0.1)
list comprehension - string 쓰지 않기
is_7 = ->n { n.abs<10 ? (n.abs==7) : is_7.(n/10) || is_7.(n%10) }
sevens = ->nth { (0..nth).select {|n| is_7.(n) || n%7==0 || n==nth } }
pingpong = ->x { sevens.(x).each_cons(2).map {|a,b| b-a }.
map.with_index {|gap,i| gap * (i.odd?? -1:1) }.sum }
# test
expect( [7, 17, -7].all? &is_7 ).to be_truthy # 7s
expect( [8, 0, -2].all? &is_7 ).to be_falsy # not 7s
expect( sevens.(20) ).to eq [0, 7, 14, 17, 20]
expect( [8, 22, 68, 100].map(&pingpong) ).to eq [6, 0, 2, 2]
expect( Benchmark.realtime { pingpong.(100000) } ).to be_between(0.001, 0.2)
recursion - 아무것도 쓰지 않기
is_7 = ->n { n.abs<10 ? n.abs==7 : is_7[n/10] || is_7[n%10] || n%7==0 }
pingpong = proc do |nth, idx, val, inc|
idx.nil? ? pingpong.(nth, 1, 1, 1) : idx == nth ? val :
pingpong.(nth, idx+1, val+inc, is_7.(idx+1) ? -inc : inc )
end
# test
expect( [8, 22, 68, 100].map(&pingpong) ).to eq [6, 0, 2, 2]
expect( Benchmark.realtime { pingpong.(1000) } ).to be_between(0.0001, 0.01)
변수를 선언하면 안된다는 조건은 통과하지 못했습니다. 재귀를 사용했는데 이또한 1000 이상은 maximum limit때문에 계산이 불가능하네요.
파이썬입니다..
def has7(n):
return n % 7 == 0 or (n % 10 and n % 10 % 7 == 0) \
or (n // 10 and has7(n // 10))
def pingpong(limit, val=1, direction=1, count=1):
if(count==limit): return val
if has7(count): direction = -direction
return pingpong(limit, val+direction, direction, count+1)
import unittest
class PingPongTest(unittest.TestCase):
def test_has7(self):
self.assertTrue(has7(7))
self.assertFalse(has7(8))
self.assertFalse(has7(10))
self.assertTrue(has7(7*22))
self.assertTrue(has7(17))
self.assertTrue(has7(170))
self.assertTrue(has7(178))
def test_pingpong(self):
self.assertEqual(6, pingpong(8))
self.assertEqual(0, pingpong(22))
self.assertEqual(2, pingpong(68))
self.assertEqual(2, pingpong(100))
if __name__ == "__main__":
unittest.main()
이런식으로 처리하면 될 것 같습니다.
int pingpong(char *wantto){
int ret = 0; int count = 1; int realdata = 1; int wanttoint = 0; char wanttostr[20];
wanttoint = atoi(wantto);
while(1){
snprintf(wanttostr, 20, "%d",count);
ret = realdata;
if(count == wanttoint) break;
if(count % 7 == 0 || strstr(wanttostr, "7")){
while(1){
count++;
snprintf(wanttostr, 20, "%d",count);
realdata --;
ret = realdata;
if(count == wanttoint || count % 7 == 0 || strstr(wanttostr, "7")) break;
}
}
if(count == wanttoint) break;
count++; realdata++;
}
return ret;
}
using System;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
Console.Write("{0}\t", pingpong(8));
Console.Write("{0}\t", pingpong(22));
Console.Write("{0}\t", pingpong(68));
Console.Write("{0}\t", pingpong(100));
Console.Write("{0}\t", pingpong(1000));
Console.Write("{0}\t", pingpong(10000));
Console.ReadKey();
}
static int pingpong(int n)
{
return n == 1 ? 1 : pingpong(n - 1) + getIncVal(n);
}
static int getIncVal(int n)
{
return n == 1 ? 1 : (n - 1) % 7 == 0 || isInclude7Cnt(n - 1) ? -getIncVal(n - 1) : getIncVal(n - 1);
}
static bool isInclude7Cnt(int n)
{
return n == 0 ? false : n % 10 == 7 ? true : isInclude7Cnt(n / 10);
}
}
}
string말고는 없애기가 힘드네요..
int sevenBool(int numbering) {
if (numbering % 7 == 0 || numbering % 10 == 7) {
return -1;
}
else if (numbering / 10 != 0) {
return sevenBool(numbering / 10);
}
else {
return 1;
}
}
int pingpong(int pingpongCount) {
int direction = 1;
int result = 0;
for (int i = 1; i <= pingpongCount; i++) {
result = result + direction;
direction = direction * sevenBool(i);
}
return result;
}
자바스크립트로 짜봤습니다.
function check7(value){
return (value%7==0||(/7/).test(value)) ? -1 : 1;
}
function pingpong(value,cnt, returnVal, direction){
cnt = cnt==undefined ? 1 : cnt;
returnVal = returnVal==undefined ? 1 : returnVal;
direction = direction==undefined ? 1 : direction;
return (value==cnt) ? returnVal
: pingpong(value, cnt+1, returnVal+direction, direction*check7(cnt+1));
}
console.log(pingpong(8));
console.log(pingpong(22));
console.log(pingpong(68));
console.log(pingpong(100));
조건이 하나 빠진 거 같아서 원문까지 살펴봤는데요, n 은 1000 미만이라는 조건이 붙어야 제약을 적용해서 풀이가 가능할 것 같은데 원문에도 그 언급이 그냥 뒤에서 슬그머니 나오네요.
def pingpong(n: int) -> int:
def has7(x: int, first=True) -> bool:
if x is 0:
return False
elif first:
if x % 7 is 0 or x % 10 is 7:
return True
elif x % 10 is 7:
return True
else:
return has7(x//10, False)
def inner(count=1, step=1, result=1):
if count == n:
return result
return inner(count+1, step if has7(count) else -step, result+ (step if has7(count) else -step))
return inner()
print(pingpong(997))
n의 크기를 한정할 수 없다고 가정하면 7이 있는지 여부를 찾는 부분도 재귀로 구성해야 합니다. 그러면 실질적으로는 997까지의 값만 구할 수 있습니다. (재귀스택에서 has7이 써버리는 부분이 있다보니..)
만약, 할당을 허용한다고 하면 꼬리재귀 호출 대신에 다음 재귀 호출에 넘길 인자를 튜플로 리턴하는 식으로 코드를 약간 뜯어고쳐서 반복문으로 만들 수 있습니다.
def pingpong(n: int) -> int:
def has7(x: int, first=True) -> bool:
if x is 0:
return False
elif first:
if x % 7 == 0 or x % 10 is 7:
return True
elif x % 10 is 7:
return True
else:
return has7(x//10, False)
def inner(count=1, step=1, result=1):
if count == n:
return result
return (count+1, step if has7(count) else -step, result+ (step if has7(count) else -step))
r = inner()
while not isinstance(r, int):
r = inner(*r)
return r
print(pingpong(1000000))
private static void pingpongRestriction(int end) {
System.out.println("pingpong (" + end + ") = " + recursiveFunc(end, 1, 1, 1));
}
// end : 종료 횟수
// count : 회차
// result : 회차의 결과값
// fluctuation : 증감값
private static int recursiveFunc(int end, int count, int result, int fluctuation) {
if (count == end) {
return result;
} else {
return recursiveFunc(end, count + 1, result + (fluctuation * fluctiationFunc(count)), fluctuation * fluctiationFunc(count));
}
}
//증감
private static int fluctiationFunc(int count) {
return ( ((count % 7) == 0) || ((count % 10) == 7) || ((count / 10) == 7) ) ? -1 : 1;
}
#include <stdio.h>
int pm(int num)
{
if (num == 0) return 1;
if (num % 7 == 0 || num % 10 == 7 || (num / 10) % 10 == 7 || num / 100 == 7)
return -pm(num - 1);
else
return pm(num - 1);
}
int pingpong(int num)
{
if (num == 1) return 1;
return pingpong(num - 1) + pm(num - 1);
}
void main(void)
{
printf("%d\n",pingpong(8));
printf("%d\n", pingpong(22));
printf("%d\n", pingpong(68));
printf("%d\n", pingpong(100));
}
허접한 풀이!! ㅠ,.ㅠ
#include<stdio.h>
#include<windows.h>
struct Sseq {
int seq;
int out;
};
int pingpong(int input);
Sseq s;
int temp;
char ch;
void main(void) {
int input;
ch = '+';
s.out = 1;
s.seq = 1;
temp = 0;
printf("#입력 : ");
scanf("%d", &input);
printf("\n#출력 : ");
printf("%d\n", pingpong(input));
}
int pingpong(int input) {
if(((s.seq % 7) == 0 || (s.seq % 10) == 7 || (s.seq/7)%10 == 0) && s.seq/7!=0) {
if(temp < s.out)
ch='-';
else
ch='+';
}
if(ch == '-') {
temp = s.out;
s.out--;
}
else {
temp = s.out;
s.out++;
}
s.seq++;
input--;
if(input > 1)
return pingpong(input);
else
return s.out;
}
자바
package study;
public class study {
public static void main(String[] args) {
System.out.println("pingpong(" + 8 + ") = " + pingpong(8));
}
public static int pingpong(int n) {
int dir = 1, result = 0;
for (int i = 1; i < n + 1; i++) {
if (dir == 1) {
result++;
} else {
result--;
}
if (i % 7 == 0 || i % 10 == 7 || (i / 10) % 10 == 7 || (i / 100) % 10 == 7 || (i / 1000) % 10 == 7) {
dir = (dir + 1) % 2;
}
}
return result;
}
}
귀찮아서 String 안 쓰고 4자리까지만 되게 했습니다 추가조건은 어려워서 요까지만...
재미있네요 ㅋㅋ
#define PINGPONG_MULTIPLES_OF_SEVEN(n) (bool)(n % 7 == 0)
bool pingpong_contains_seven(int num)
{
if (num >= 10)
{
if (num % 10 == 7)
return true;
return pingpong_contains_seven(num / 10);
}
return num == 7;
}
int pingpong_check(int value, bool increased, int play_num, int play_max)
{
if (play_num > play_max)
return value;
if (PINGPONG_MULTIPLES_OF_SEVEN(play_num) ||
pingpong_contains_seven(play_num))
return pingpong_check(increased ? value + 1 : value - 1, !increased, play_num + 1, play_max);
return pingpong_check(increased ? value + 1 : value - 1, increased, play_num + 1, play_max);
}
int pingpong(int number)
{
return pingpong_check(0, true, 1, number);
}
printf("%d : %d\n", 8, pingpong(8));
printf("%d : %d\n", 22, pingpong(22));
printf("%d : %d\n", 68, pingpong(68));
printf("%d : %d\n", 100, pingpong(100));
8 : 6 22 : 0 68 : 2 100 : 2
def _7(n):
if n%10 == 7: return True
elif n == n%10: return False
else: return _7(n//10)
def p(n, i, s, d):
if n == i: return s
if i%7 == 0 or _7(i): return p(n, i+1, s-d, (-d))
else: return p(n, i+1, s+d, d)
def pingpong(n): return p(n, 1, 1, 1)
print(pingpong(8))
print(pingpong(22))
print(pingpong(68))
print(pingpong(100))
제약은 다 지켰지만 실제로 쓰기에는 무리가 있네요.큰 수 넣으면 재귀 최대 깊이 초과라 그냥 루프 돌리는 것이 코딩도 쉽고 안정적일 것 같네요.
import sys
sys.setrecursionlimit(10000)
def has_7(n):
if n == 0:
return False
elif n%7 == 0 or n%10 == 7:
return True
elif n%10 == n: # 위 조건과 자리 바뀌면 안됨
return False
else:
return has_7(n//10)
def f(x, i=1, n=1, step=1):
if x == i:
return n
if has_7(i):
return f(x, i+1, n-step, step*-1) # n-step 주의
return f(x, i+1, n+step, step)
f(8), f(22), f(68), f(100), f(1000)
문제 뼈대를 옮겨보면..
int main(int argc, const char * argv[]) {
printf("%d\n", pingpong(8));
printf("%d\n", pingpong(22));
printf("%d\n", pingpong(68));
printf("%d\n", pingpong(100));
return 0;
}
자리 인덱스 n을 1부터 시작하므로 루프에서 for (int i=1; i<=n; i++)처럼...
int pingpong(int n) {
int step = 1;
int value = 0;
for (int i=1; i<=n; i++) {
value += step;
if (i % 7 == 0 || contains7(i) ) { // 7의배수거나 7을 포함하거나..
step = -step;
}
}
return value;
}
7을 포함하는 것은 각 자릿수(%10)를 확인하면 됩니다.
int contains7(int n) {
while (n > 0) {
if (n % 10 == 7) return 1;
n /= 10;
}
return 0;
}
그런데, for 루프와 대입문을 사용하지 말자.. 라는 것은 재귀호출을 이용하라는 의미같아요.
pingpong은 재귀함수를 하나 뽑아내서..
int pingpong_(int n, int i, int step, int value) {
if (i<=n) {
return pingpong_(n, i+1, (i % 7 == 0 || contains7(i)) ? -step : step, value + step);
} else {
return value;
}
}
int pingpong(int n) {
return pingpong_(n, 1, 1, 0);
}
contains7도 재귀로 바꿀 수 있겠네요.
int contains7(int n) {
if (n % 10 == 7) return 1;
if (n == 0) return 0;
return contains7(n / 10);
}
def pingpong(x):
if x == 1 or x == 2:
return pingPongList[x-1]
elif x%7 == 1 or '7' in str(x-1):
if pingPongList[x-3] < pingPongList[x-2]:
pingPongList.append(pingPongList[x-2] - 1)
return pingPongList[x-1]
else:
pingPongList.append(pingPongList[x-2] + 1)
return pingPongList[x-1]
else:
if x<=0 or int(x)!=x:
pass
elif pingPongList[x-3] < pingPongList[x-2]:
pingPongList.append(pingPongList[x-2]+1)
return pingPongList[x-1]
else:
pingPongList.append(pingPongList[x-2]-1)
return pingPongList[x-1]
while True:
pingPongList = [1, 2]
num = int(input('개수를 입력하십시오: '))
for i in range(1, num+1):
print('단계:%s 핑퐁숫자: %s'%(i, pingpong(i)))
public class test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int number = scan.nextInt();
System.out.println("pingpong(" + number + ") = "+ pingpong(number));
}
public static int pingpong(int end) {
int result = 0; // return 결과값
boolean flag = true; // +,- 분기
// true 일 경우 +
// false 일경우 -
for(int i = 1 ; i <= end ; i ++) { // end 값만큼 반복
result = flag? result+1 : result-1; // flag에 따른 result 값 + or -
boolean flag1 = (i % 7 == 0); // 7의 배수
boolean flag2 = (i + "").contains("7"); // 7 포함 유무
if(flag1 || flag2) {
flag = flag?false:true; // 위 조건 충족시 반대값 대입
}
}
return result; // 결과 return
} // pingpong end
}
심화는 확실히 어렵네요.. 오늘도 부족함만 잔뜩 느끼고 가는중... 아래는 아직 많이 부족한 심화 코드요 ㅠㅠ
public class test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int end = scan.nextInt(); // 종료값 입력
end = end < 1 ? 1 : end == 0 ? 1 : end; // 종료값 음수, 0 방지
System.out.println("pingpong(" +end + ") = " + pingpong(end));
}
public static int pingpong(int end) {
return pingpong(0,1,end,true); // 시작값, 회차, 종료값, + or -에 대한 flag
}
public static int pingpong(int num, int count, int end, boolean flag) {
num = flag ? num + 1 : num - 1;
flag = (includeSeven(count) || count % 7 == 0) ? (flag ? false : true ) : flag;
return count == end ? num : pingpong(num, count+1, end, flag);
}
public static boolean includeSeven(int count) {
return count % 10 == 7 ? true : (count > 9) ? includeSeven(count/10) : false ;
}
}
def check (x, y):
if x % 7 == 0 or '7' in str(x): return y * (-1)
else: return y
def findsol (target, count, answer, op):
if count == target: print(answer);
else: findsol(target, count + 1, answer + check(count, op), check(count,op))
def pingpong(x): return findsol(x,1,1,1)
파이썬 2.7으로 작성하였습니다.
def sevenCount(num):
if num == 0 : return 0
elif '7' in str(num) or num % 7 == 0: return 1+sevenCount(num-1)
else : return sevenCount(num-1)
def pingpong(num):
if num == 0: return 0
else : return pingpong(num-1)+pow(-1,sevenCount(num-1))
print pingpong(22)
MATLAB 입니다.
if 조건문의 향연이네요 ㅜㅠ
pingpong(8)
pingpong(22)
pingpong(68)
pingpong(100)
6
0
2
2
나옵니다
function [nth_number,p_m_sign]=pingpong(val)
if val==1
nth_number=1;
p_m_sign=1;
else
[prev_nth_number,prev_p_m_sign]=pingpong(val-1);
nth_number=prev_nth_number+prev_p_m_sign;
if mod(val,7)==0 || has_7(val)==1
p_m_sign=-1*prev_p_m_sign;
else
p_m_sign=prev_p_m_sign;
end
end
end
function result=has_7(val)
if val<10
if val==7
result=1;
else
result=0;
end
elseif rem(val,10)==7
result=1;
else
result=has_7(floor(val/10));
end
end
/**
* URL : http://codingdojang.com/scode/514
* 각자리수를 찾는 방법을 재귀로 구현
*/
public class PingPong {
public static void main(String[] args) {
pingpong(68);
}
private static void pingpong(int n) {
ping(1, 1, n, 1);
}
private static void ping(int i, int v, int n, int d) {
if (i == n) {
System.out.println(i + " " + v);
return;
}
i = i + 1;
v = v + d;
boolean b = pong(i, 10);
if (i % 7 == 0 || b) {
d = d * -1;
}
ping(i, v, n, d);
}
private static boolean pong(int i, int d) {
if ((i / d) < 10) return false;
if (i % d == 7) return true;
return pong(i, 10 * d);
}
}
#include <iostream>
void Pingpong(int cnt);
using namespace std;
int main()
{
int number;
cin >> number;
Pingpong(number);
return 0;
}
void Pingpong(int cnt)
{
bool is_include7 = false;
int temp, data, sign;
data = 0;
sign = 1;
for (int i = 0; i < cnt; i++)
{
data += sign;
temp = i + 1;
while (temp != 0) // n번째의 n이라는 숫자에 7이란 숫자가 포함되었는지?
{
if (temp % 10 == 7) {
is_include7 = true;
break;
}
temp /= 10;
}
if (((i + 1) % 7 == 0) || is_include7 == true) //n번째의 n이라는 숫자가 7의 배수이거나 7을 포함하면?
sign = -sign; //부호 변경
is_include7 = false;
cout << data << " ";
}
cout << endl;
cout << "Result: " << data << endl;
}
var direction = (c, d) => c % 7 === 0 || /7/.test(c) ? -d : d;
var pingpong = function(t, n = 0, c = 1, d = 1) {
return c === t ? n + d : pingpong(t, n + d, c + 1, direction(c, d));
};
console.log(pingpong(8)); // = 6
console.log(pingpong(22)); // = 0
console.log(pingpong(68)); // = 2
console.log(pingpong(100)); // = 2
object PingPong
{
def IsInclude7(N: Int, sN: String): Int = if(((0 until sN.length) map(sN(_).toInt)).lastIndexOf(55) != -1) 1 else 0
def IsDivided7(N: Int): Int = if(N % 7 == 0) 1 else 0
def Interface7(N: Int): Int = IsInclude7(N,s"$N") + IsDivided7(N)
def TnFToInt(B: Boolean): Int = if(B) 1 else -1
def PingPongGo(N: Int, i: Int, Direction : Boolean, Finish: Int, PPSeq: IndexedSeq[Int]): IndexedSeq[Int] = {
if(i < Finish)
{
if(Interface7(i) == 0)
PingPongGo(N+TnFToInt(Direction),i+1,Direction,Finish, PPSeq:+N)
else
PingPongGo(N-TnFToInt(Direction),i+1,!Direction,Finish, PPSeq:+N)
}
else
PPSeq:+N
}
def PingPongStart(Finish: Int): IndexedSeq[Int] = PingPongGo(1,1,true,Finish,IndexedSeq[Int]())
def main(Args : Array[String]): Unit = print(PingPongStart(50))
}
심화는 아직 생각해봐야겠습니다..
def pingpong(n):
x, d = 1, 1
for i in range(2, n + 1):
x += d
if i % 7 == 0 or '7' in str(i):
d = -d
return x
for n in [8, 22, 68, 100]:
print('pingpong(%d) = %d' % (n, pingpong(n)))
심화
def contain7(i):
if i == 0: return False
elif i % 10 == 7: return True
else: return contain7(i // 10)
def nextdir(d, i):
return -d if (i % 7 == 0 or contain7(i)) else d
def pingpong(n, x=1, d=1, i=1):
return x if i == n else pingpong(n, x + nextdir(d, i), nextdir(d, i), i + 1)
def ping_pong(n) :
result = []
a = 1
plus = 1
for s in range(1, n + 1) :
result.append(a)
if str(s)[-1] == '7' or s % 7 == 0 :
if plus == 1 :
plus = -1
a += plus
else :
plus = 1
a += plus
else :
a += plus
return result[-1]
def pingpong(x): if x==1: return 1 if x==2: return 2 direction=pingpong(x-1)-pingpong(x-2) if (x-1)%7==0 or (x-1)/10%7==0 or (x-1)/100%7==0: return pingpong(x-1)-direction return pingpong(x-1)+direction print(pingpong(8)) 세자리수까지
참 더러운 코드지만 용서해주세용..
#include<iostream>
using namespace std;
int pingpong(int _num)
{
int num[100];
bool sw = false;
int countNum = 1;
for (int i = 0; i < 100; i++)
{
if (!sw)
{
num[i] = countNum;
if ((i + 1) % 7 == 0 || (i + 1) % 10 == 7 || ((i + 1) % 100) / 10 == 7 ) //7의 배수 이거나 첫째 자리수가 7이면
sw = true;
else
countNum++;
}
else
{
num[i] = countNum - 1;
if ((i + 1) % 7 == 0 || (i + 1) % 10 == 7 || ((i + 1) % 100) / 10 == 7)
sw = false;
else
countNum--;
}
}
return num[_num - 1];
}
int main()
{
cout << pingpong(8) << endl;
cout << pingpong(22) << endl;
cout << pingpong(68) << endl;
cout << pingpong(100) << endl;
}
import Control.Applicative
merge :: (Eq a, Ord a) => [a] -> [a] -> [a]
merge xs [] = xs
merge [] ys = ys
merge (x:xs) (y:ys)
| x > y = y : merge (x:xs) ys
| x < y = x : merge xs (y:ys)
| x == y = x : merge xs ys
pingpong :: Int -> Int -- fmap pingpong [1..] == [1, 2, 3, 4, 5, 6, 7, 6, 5, ...]
pingpong n = sum $ zipWith (*) (cycle [1,-1]) $ zipWith (-) =<< tail $ takeWhile (< n) extrema ++ [n]
extrema :: [Int] -- extrema == [0, 7, 14, 17, 21, 27, 28, ...]
extrema = merge [0, 7..] $ [0..] >>= \n -> foldr1 merge $ fmap (sevens n) [0..n]
where
sevens m n
| m == n = liftA2 (+) [7*10^n] [0..10^n-1]
| otherwise = liftA2 (+) [10^m + 7*10^n, 10^m + 17*10^n..10^(m+1)] [0..10^n-1]
main = print $ pingpong 10000000
naive
import Control.Applicative
pingpong' :: Int -> Int
pingpong' n = sum $ scanl acc 1 [1..n-1]
acc s n = if liftA2 (||) cond1 cond2 n then -s else s
cond1 = (==0) . (`rem` 7)
cond2 = any (==7) . fmap (`rem` 10) . takeWhile (/= 0) . iterate (`div` 10)
main = print $ pingpong' 10000000
자바요
public static void main(String[] args)
{
main ma = new main();
System.out.println(ma.pingpong(100));
}
public int pingpong(int num)
{
return recursiveFunc(num, 1, 1, 0);
}
public int recursiveFunc(int end, int cur, int cnt, int updown)
{
if(cnt == end)
{
return cur;
}
else
{
if(cnt % 7 == 0 || cnt % 10 == 7 || cnt / 10 == 7)
{
if(updown == 0)
{
return recursiveFunc(end, cur-1, cnt+1, 1);
}
else
{
return recursiveFunc(end, cur+1, cnt+1, 0);
}
}
else
{
if(updown == 0)
{
return recursiveFunc(end, cur+1, cnt+1, 0);
}
else
{
return recursiveFunc(end, cur-1, cnt+1, 1);
}
}
}
}
파이썬 3.6
def check_7(n):
if n%10 == 7:
return True
elif n//10 == 7:
return True
elif n%10 != 7 and n//10 != 7 and (n//10)//10 == 0:
return False
else:
n = n//10
if check_7(n):
return True
else:
return False
def pingpong(n):
t,num,direction = 1,0,1
while t <= n:
if t % 7 == 0 or check_7(t):
if direction == 1:
num += 1
direction -= 1
else:
num -= 1
direction += 1
else:
if direction == 1:
num += 1
else:
num -= 1
t += 1
print("pingpoing(%d) = %d"%(t-1,num))
if __name__ == "__main__":
# n = int(input(''))
pingpong(8)
pingpong(22)
pingpong(68)
pingpong(100)
pingpong(1000000)
pingpoing(8) = 6
pingpoing(22) = 0
pingpoing(68) = 2
pingpoing(100) = 2
pingpoing(1000000) = -868
n = 1000000인 경우 2초 내로 나옵니다.
def check7(n):
if n%7 == 0:
return True
else:
while 1:
if n%10 ==7:
return True
if n//10 == 0:
break
n = n//10
return False
def pingpong(n):
increase = 1
i = 1
num = 1
while i < n:
i += 1
num += increase
if check7(i):
increase = increase*(-1)
return num
def pingpong(n):
m=1
ad=1
for i in range(1,n):
if 0==(1-('7' in str(i)))* (1-(i%7==0)):
ad= ad*(-1)
m+=ad
return m
#include <stdio.h>
int main() {
int input, re=1, ad=1, mu, temp;
printf("숫자를 입력하시오.\n");
scanf_s("%d", &input);
for (int i = 1; i < input; i++) {
mu = i%7;
temp = i;
while (temp > 0) {
mu *= 1-((temp % 10) == 7);
temp = temp / 10;
}
if (mu == 0){
ad = ad * (-1);
}
re += ad;
}
printf("%d", re);
return 0;
}
def pingpong(x):
a=1
b=0
for i in range(1,x+1):
b=b+(1*a)
if i%7==0 or '7' in str(i) : a=a*(-1)
return b
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
int cnt = 0;
int ping = 0;
boolean seven = false;
for (int i=0; i<t; i++) {
cnt++;
ping = seven ? ping-1 : ping+1;
if(String.valueOf(cnt).contains("7") || cnt % 7 == 0)
seven = !seven;
}
System.out.println(ping);
} // 스트링을 안쓰고 cnt가 7을 포함하느냐 구별하는 건 정규식을 사용해야 될 거 같은데 일단은 여기까지 했습니다... 심화과정은 다음에 해야지
Swift입니다.
Loop, Assignment, String없이 풀었습니다. 위 조건을 맞추려니, 재귀호출뿐이 없네요.
func contains7(_ number: Int) -> Bool {
return number % 10 == 7 ? true : (number / 10 < 1 ? false : contains7(number / 10))
}
func pingpong(_ target: Int, _ direction: Int = 1, _ number: Int = 0, _ count: Int = 0) -> Int {
if count == target {
return number
}
if (count + 1) % 7 == 0 || contains7(count + 1) {
return pingpong(target, direction * -1, number + direction, count + 1)
}
return pingpong(target, direction, number + direction, count + 1)
}
print( pingpong(8) )
print( pingpong(22) )
print( pingpong(68) )
print( pingpong(100) )
print( pingpong(1000) )
결과는...
6
0
2
2
-26
순서대로 진행해 나가면서 direction으로 방향만 전환하며 더해주는 방법으로 풀었습니다. 7을 포함하는지 확인 작업과 순서대로 진행하는 것을 재귀를 사용했기 때문에 문자열이나, 변수 할당을 사용할 필요가 없습니다.
def pingPong(N:Int):Int ={
def has_seven(num:Int):Boolean = {
num match {
case 0 => false
case x if num % 10 == 7 => true
case _ => has_seven(num / 10)
}
}
def step(n:Int, direction:Int, ans:Int):Int = {
n match {
case x if n == N => ans
case x if n % 7 == 0 || has_seven(n) => step(n + 1, -1*direction, ans + -1*direction)
case _ => step(n + 1, direction, ans + direction)
}
}
step(1, 1 , 1)
}
println(pingPong(8))
println(pingPong(22))
println(pingPong(68))
println(pingPong(100))
public class PingPong {
public static void main(String[] args) {
pingpong(100);
}
private static void pingpong(int Q) {
int num = 0;
int sw = 1;
int count = 0;
while (Q != count++) {
num += sw;
if (count % 7 == 0 || (count + "").contains("7"))
sw *= -1;
}
System.out.println(num);
}
}
public class PingPong {
public static void main(String[] args) {
pingpong(8);
pingpong(22);
pingpong(68);
pingpong(100);
}
private static void pingpong(int Q) {
int num = 0;
int sw = 1;
int count = 0;
while (Q != count++) {
num += sw;
if (count % 7 == 0 || Check(count))
sw *= -1;
}
System.out.println(num);
}
private static boolean Check(int num) {
return (num % 10 == 7 || (num > 0 && Check(num / 10)) ? true : false);
}
}
public class PingPong {
public static void main(String[] args) {
pingpong(8);
pingpong(22);
pingpong(68);
pingpong(100);
}
private static void pingpong(int Q) {
Cal(0, 0, -1, Q);
}
private static int Cal(int num, int count, int sw, int Q) {
if (count % 7 == 0 || Check(count))
sw *= -1;
num += sw;
if (Q == 1) {
System.out.println(num);
return num;
}
Cal(num, ++count, sw, --Q);
return num;
}
private static boolean Check(int num) {
return (num % 10 == 7 || (num > 0 && Check(num / 10)) ? true : false);
}
}
def pingpong1(a):
ping,pm = [1],1
while a != len(ping):
ping.append(ping[-1] + pm)
if len(ping) % 7 == 0 or str(len(ping)) in '7':
pm *= -1
print(ping[-1])
def pingpong(x):
p,r = 0,0
for i in range(1,x+1):
r = r + (-1)**p
if i%7 == 0 or '7' in str(i): p = (1,0)[p]
return r
def pingpong(_input):
if _input<8:
return _input
t=[i for i in range(1,_input+1) if (i%7 ==0) or ('7' in str(i))]
a=[t[i]-t[i-1] for i in range(1,len(t))]
c=list(map(lambda x: x[1] if x[0]%2==1 else -x[1], enumerate(a)))
return 7+sum(c)+t[-1]-_input if len(t)%2==1 else 7+sum(c)-t[-1]+_input
def includeSeven(n): #숫자에 7이 포함돼있는지 확인하는 함수
while n != 0:
if n%10 == 7: return True
n = n//10
#n이 세자리수 이하일 때는 아래와 같이 변수할당없이 표현가능
#if n%10==7 or (n//10)%10==7 or (n//100)%10: return True
return False
def f(n, sign, k, _max): #재귀함수
if k >= _max:
return n
if k%7 == 0 or includeSeven(k):
return f(n + (-1)*sign, (-1)*sign, k+1, _max)
return f(n + sign, sign, k+1, _max)
def pingpong(n):
return f(1, 1, 1, n)
>>> pingpong(8)
6
>>> pingpong(22)
0
>>> pingpong(68)
2
>>> pingpong(100)
2
def seven(s) :
if s % 7 == 0 :
return True
if s % 10 == 7 :
return True
if 80 > s % 100 > 69 :
return True
if 800 > s % 1000 > 699 :
return True
return False
# k, i, n, o는 각각 초기치, 스텝, 초기 항 번호, 목표 항 번호
def ping(k, i, n, o) :
if n == o :
return k
elif seven(n) == True :
return ping(k-i, -i, n+1, o)
elif seven(n) == False :
return ping(k+i, i, n+1, o)
def pingpong(p) :
return ping(1, 1, 1, p)
print(pingpong(8))
print(pingpong(22))
print(pingpong(68))
print(pingpong(100))
재귀함수를 익히는데 아주 좋은 기회가 됐습니다.
결과
6
0
2
2
#파이썬
#처음에 쉽게 문제를 풀었다가 제약조건이 있는걸 보고
#배열도 없애고 String도 없앴습니다
#변수 할당을 하지 말것은 변수 자체를 쓰지 마라는 의미인가요?
#변수를 안쓰고는 도저히 어떻게 해야할지 모르겠습니다 ㅜㅜㅜ
def pingpong(x):
p,pp,sign=0,0,1
while (pp<x):
p+=sign
pp+=1
if pp%7==0 or pp%10==7 or pp//10==7 or pp//100==7:
sign*=-1
print ('pingping(',x,')=',p)
pingpong(8)
pingpong(22)
pingpong(68)
pingpong(100)